This is hopefully the results section for the Study 2 NSE & SE babies watching ASL Stories. We have two main factors:

  1. Language (Sign v. English)
  2. Direction (Forward v. Reversed)

Ages of babies are from 5 to 14.99 months. That means we lose two “old” CODA babies - Janine (16 mo) and za02 (23 mo). The dataset also contains factors for younger v. older babies IF we want to do age group splits. I do not recommend it because we lose all significance that way and we have more precise age information, better than brute groups. IF we do use it, the baby age groups are such:

  • Younger babies = 5 to 8.99 months
  • Older babies = 9.0 to 14.99 months

To skip to the XY Data, go here. To skip to the AOI/FCR analysis, go here.

Demographics

library(tidyverse)
library(janitor)
library(lme4)
library(lmerTest)
library(scales)
library(feather)
library(GGally)
# Grab data that was produced in 03importcleanbabies.Rmd
babies <- read_feather("cleanedbabyeyedata.feather") %>%
  mutate(age = age*12) %>%
  select(participant, language, age, gender, story, direction, mark, trial, repetition, aoi, secs, percent) %>%
  rename(name = participant) %>%
  mutate(agegroup = case_when(
    age <= 8.99 ~ "younger",
    age >= 9.0 & age < 15 ~ "older"
  )) %>%
  filter(!is.na(agegroup)) %>%
  mutate(language = case_when(
    language == "english" ~ "NSE",
    language =="sign" ~ "SE"
  )) %>%
  rename(lang = language) %>%
  mutate(lang2 = case_when(
    name == "aubrey CODA 11m" ~ "HSE",
    name == "GemmaF_11_4_13_CODA" ~ "HSE",
    name == "Hannah_CODA_7m" ~ "HSE",
    name == "ke11es12_7m_MomTerp" ~ "LSE",
    name == "Miles_14m_SE" ~ "HSE",
    name == "Parker 6 m SIGNING" ~ "HSE",
    name == "Penn 6 months SIGN EXPOSED" ~ "HSE",
    name == "Trinity 8m" ~ "LSE",
    name == "Victoria07_18_17" ~ "LSE",
    name == "Wells_8mos" ~ "LSE",
    TRUE ~ lang
  ))
#  filter(name != "Victoria07_18_17")
babiesinfo <- babies %>%
  select(name, lang, age, gender) %>%
  distinct() %>%
  group_by(lang) %>%
  summarise(N = n(),
            age_mean = mean(age),
            sd = sd(age),
            min = min(age),
            max = max(age))
genders <- babies %>%
  select(name, lang, age, gender) %>%
  distinct() %>%
  group_by(lang, gender) %>%
  summarise(N = n()) %>%
  spread(gender, N)
babiesinfo <- left_join(babiesinfo, genders) %>%
  select(lang, N, Female, Male, age_mean, sd, min, max) %>%
  print()
babies$agegroup <- fct_relevel(babies$agegroup, c("younger","older"))
# IF we do age groups, use this code
# 
# babiesinfo <- babies %>%
#   select(name, lang, age, agegroup, gender) %>%
#   distinct() %>%
#   group_by(lang, agegroup) %>%
#   summarise(N = n(),
#             age_mean = mean(age),
#             sd = sd(age),
#             min = min(age),
#             max = max(age))
# 
# genders <- babies %>%
#   select(name, lang, age, agegroup, gender) %>%
#   distinct() %>%
#   group_by(lang, agegroup, gender) %>%
#   summarise(N = n()) %>%
#   spread(gender, N)
# 
# babiesinfo <- left_join(babiesinfo, genders) %>%
#   select(lang, agegroup, N, Female, Male, age_mean, sd, min, max) %>%
#   print()

Global Looking

We calculated percentages based on overall clip length as the denominator. In this way, we can meaningfully contrast looking times at the videos (which are variable lengths) based on different factors. But when we go to AOI analysis we need to re-calculate the percentages so the denominator is based on total looking time, not overall clip length.

The chart below shows little differences based on factors Age, Language, or Direction. That’s good, means the videos were equally engaging for all babies, right?

babies$lang <- as.factor(babies$lang)
babies_overall_looking <- babies %>%
  group_by(name, age, lang, direction, story, repetition) %>%
  summarise(percent = sum(percent)) # gets total looking percent for each trial for each baby
# Table of means
babies_overall_looking %>% 
  group_by(name, lang, direction) %>%
  summarise(percent = mean(percent)) %>% # get average looking percent for each baby
  group_by(lang, direction) %>%
  summarise(mean_percent = mean(percent),
            count = n(),
            sd = sd(percent),
            se = sd/sqrt(count)) %>%
  select(-sd) %>%
  print()
ggplot(babies_overall_looking, aes(x = age, y = percent, color = direction, fill = direction)) + 
  geom_jitter(alpha = 0.5) +
  facet_grid(. ~ lang) +
  geom_smooth(method = "lm", se = FALSE) +
  ggtitle("Video Attention") +
  xlab("age (months)") +
  ylab("percent looking") + 
  theme_bw() + 
  scale_y_continuous(limits = c(0,1), labels = percent) 

# Plot
# babies_overall_looking %>% 
#   group_by(lang, direction, name) %>%
#   summarise(percent = mean(percent)) %>% # gets average looking percent for each baby
#   group_by(lang, direction) %>%
#   summarise(mean_percent = mean(percent), # gets group averages
#             count = n(),
#             sd = sd(percent),
#             se = sd/sqrt(count)) %>% 
#   ggplot(aes(x = lang, y = mean_percent, fill = direction)) + 
#   geom_col(position = "dodge") + 
#   geom_errorbar(aes(ymin = mean_percent - se, ymax = mean_percent + se), 
#                 position = position_dodge(width = 0.9), width = 0.25) + 
#   scale_y_continuous(limits = c(0,1), labels = percent) +
#   theme_minimal() + 
#   theme(panel.grid.major.x = element_blank()) +
# #  facet_wrap("lang") +
#   ggtitle("Video Attention") +
#   xlab("") +
#   ylab("percent looking")
# babies_overall_looking %>%
#   ggplot(aes(x = lang, y = percent, fill = direction)) +
#   facet_wrap("agegroup") + 
#   geom_violin()

A linear model shows there were no significant effects of any factors. We can conclude there was no effect on how much the babies looked at the stimuli.

global_lm <- lmer(percent ~ age + lang * direction + (direction|name) + (direction|story), data = babies_overall_looking)
summary(global_lm) 
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: percent ~ age + lang * direction + (direction | name) + (direction |      story)
   Data: babies_overall_looking

REML criterion at convergence: -109.5

Scaled residuals: 
     Min       1Q   Median       3Q      Max 
-2.17439 -0.71127 -0.01207  0.70541  2.47192 

Random effects:
 Groups   Name              Variance  Std.Dev. Corr 
 name     (Intercept)       0.0103084 0.10153       
          directionreversed 0.0009282 0.03047  1.00 
 story    (Intercept)       0.0086180 0.09283       
          directionreversed 0.0039286 0.06268  -0.76
 Residual                   0.0330635 0.18183       
Number of obs: 349, groups:  name, 26; story, 8

Fixed effects:
                          Estimate Std. Error        df t value Pr(>|t|)    
(Intercept)               0.679103   0.086923 28.572445   7.813 1.43e-08 ***
age                       0.002021   0.008959 23.305300   0.226    0.824    
langSE                   -0.049624   0.050507 23.785326  -0.983    0.336    
directionreversed        -0.033434   0.034821 12.347582  -0.960    0.355    
langSE:directionreversed  0.019263   0.041732 94.210799   0.462    0.645    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) age    langSE drctnr
age         -0.854                     
langSE      -0.051 -0.197              
dirctnrvrsd -0.228  0.006  0.068       
lngSE:drctn  0.034 -0.001 -0.126 -0.497
#ggcoef(global_lm)

AOI Looking

Now we’ll re-calculate the percentages so the denominator is based on total looking time. All AOIs should sum up to 100% for each trial and each baby. Next let’s make a boxplot of all AOIs.

#Recalculate percent
babies <- babies %>%
  select(-percent) %>%
  group_by(name, lang, agegroup, age, direction, story, mark, trial, repetition, gender) %>%
  mutate(totalsec = sum(secs)) %>%
  group_by(name, lang, agegroup, age, direction, story, mark, trial, repetition, gender, aoi) %>%
  mutate(percent = secs/totalsec)
# Boxplot
babies %>%
  ggplot(aes(x = aoi, y = percent, fill = direction)) + 
  geom_boxplot() +
  ggtitle("AOI Attention") +
  theme_bw() + 
  xlab("") +
  theme(axis.text.x = element_text(angle=45, hjust = 1),
        panel.grid.major.x = element_blank()) +
  scale_y_continuous(labels = scales::percent, limits = c(0,1))

It appears two important AOIs are MidChestTop and MidFaceBottom. Let’s look again only at midline AOIs:

midline = c("Belly","BelowChest","MidChestBottom","MidChestCenter","MidChestTop",
            "MidFaceBottom","MidFaceCenter","MidFaceTop")
babies %>%
  filter(aoi %in% midline) %>%
  ggplot(aes(x = aoi, y = percent, fill = direction)) + 
  geom_boxplot() +
  ggtitle("Midline AOI Attention") +
  theme_bw() + 
  xlab("") +
  theme(axis.text.x = element_text(angle=45, hjust = 1),
        panel.grid.major.x = element_blank()) +
  scale_y_continuous(labels = scales::percent, limits = c(0,1))

I’m going to run linear models with only MidChestTop or MidFaceBottom, and see what happens. No age interactions.

MidChestTop:

  • Significant effect of age (p = 0.004) - older babies look at MidChestTop AOI more.
  • Significant effect of language (p = 0.006) - NSE babies look +14.6% more than SE babies.
  • Significant effect of direction (p = 0.046) - Babies look about 4.5% less for reversed
  • No language X direction interaction.

MidFaceBottom:

  • No effect of age
  • Significant effect of language (p = 0.004) - SE babies look +21% more than NSE babies.
  • Marginal effect of language (p = 0.073) - Babies look about 2% more for reversed.
  • No language X direction interaction.
babies %>%
  filter(aoi %in% c("MidFaceBottom","MidChestTop")) %>%
  ggplot(aes(x = age, y = percent, color = direction, fill = direction)) + 
  geom_jitter(alpha = 0.5) + 
  geom_smooth(method = "lm", se = FALSE) +
  scale_y_continuous(limits = c(0,1), labels = percent) +
  theme_bw() + 
#  theme(panel.grid.major.x = element_blank()) +
  facet_grid(aoi ~ lang) +
  ggtitle("AOI Attention") +
  xlab("") +
  ylab("percent looking")

midchesttop_lm <- lmer(percent ~ age + lang * direction + (1|name) + (1|story), data = filter(babies, aoi == "MidChestTop"))
summary(midchesttop_lm)
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: percent ~ age + lang * direction + (1 | name) + (1 | story)
   Data: filter(babies, aoi == "MidChestTop")

REML criterion at convergence: -215.2

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-3.0246 -0.7130 -0.1414  0.6022  2.6752 

Random effects:
 Groups   Name        Variance  Std.Dev.
 name     (Intercept) 0.0114441 0.1070  
 story    (Intercept) 0.0002891 0.0170  
 Residual             0.0253365 0.1592  
Number of obs: 349, groups:  name, 26; story, 8

Fixed effects:
                           Estimate Std. Error         df t value Pr(>|t|)   
(Intercept)                0.110030   0.076921  23.643715   1.430  0.16568   
age                        0.029452   0.008477  22.192885   3.474  0.00213 **
langSE                    -0.134837   0.050436  27.916006  -2.673  0.01240 * 
directionreversed         -0.043631   0.022400 320.218547  -1.948  0.05232 . 
langSE:directionreversed   0.038910   0.034773 317.931790   1.119  0.26400   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) age    langSE drctnr
age         -0.912                     
langSE      -0.076 -0.188              
dirctnrvrsd -0.137 -0.002  0.213       
lngSE:drctn  0.084  0.006 -0.336 -0.645
#ggcoef(midchesttop_lm)
midfacebottom_lm <- lmer(percent ~ age + lang * direction + (1|name) + (1|story), data = filter(babies, aoi == "MidFaceBottom"))
summary(midfacebottom_lm)
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: percent ~ age + lang * direction + (1 | name) + (1 | story)
   Data: filter(babies, aoi == "MidFaceBottom")

REML criterion at convergence: -157.6

Scaled residuals: 
     Min       1Q   Median       3Q      Max 
-2.42325 -0.77817 -0.02519  0.70580  2.50539 

Random effects:
 Groups   Name        Variance Std.Dev.
 name     (Intercept) 0.019877 0.14099 
 story    (Intercept) 0.002498 0.04998 
 Residual             0.028516 0.16887 
Number of obs: 349, groups:  name, 26; story, 8

Fixed effects:
                           Estimate Std. Error         df t value Pr(>|t|)   
(Intercept)                0.334139   0.099651  25.233307   3.353  0.00253 **
age                       -0.008939   0.010886  22.948912  -0.821  0.42004   
langSE                     0.193693   0.063648  26.900910   3.043  0.00518 **
directionreversed          0.038727   0.023881 317.208664   1.622  0.10587   
langSE:directionreversed  -0.052616   0.036996 315.990174  -1.422  0.15595   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) age    langSE drctnr
age         -0.903                     
langSE      -0.065 -0.193              
dirctnrvrsd -0.112 -0.002  0.179       
lngSE:drctn  0.069  0.006 -0.283 -0.647
#ggcoef(midfacebottom_lm)
# Bar chart
# babies %>%
#   filter(aoi %in% c("MidFaceBottom","MidChestTop")) %>%
#   group_by(agegroup, lang, direction, name, aoi) %>%
#   summarise(percent = mean(percent)) %>% # gets average looking percent for each baby
#   group_by(agegroup, lang, direction, aoi) %>%
#   summarise(mean_percent = mean(percent), # gets group averages
#             count = n(),
#             sd = sd(percent),
#             se = sd/sqrt(count)) %>% 
#   ggplot(aes(x = lang, y = mean_percent, fill = direction)) + 
#   geom_col(position = "dodge") + 
#   geom_errorbar(aes(ymin = mean_percent - se, ymax = mean_percent + se), 
#                 position = position_dodge(width = 0.9), width = 0.25) + 
#   scale_y_continuous(limits = c(0,1), labels = percent) +
#   theme_minimal() + 
#   theme(panel.grid.major.x = element_blank()) +
#   facet_grid(aoi ~ agegroup) +
#   ggtitle("Video Attention") +
#   xlab("") +
#   ylab("percent looking")

Face-Chest Ratio

Next, we’ll define a Face-Chest Ratio (FCR) such that:

  1. MidFaceCenter, MidFaceBottom = Face
  2. MidChestTop, MidChestCenter, MidChestBottom, BelowChest = Chest
  3. FCR = face - chest / face + chest

We did not include Belly or MidFaceTop because of very low looking rates according to the boxplots above.

babies_fcr <- babies %>%
  spread(aoi,percent) %>%
  group_by(name, age, agegroup, lang, gender, direction, story, repetition) %>%
  summarise(face = sum(MidFaceCenter, MidFaceBottom, na.rm = TRUE),
         chest = sum(MidChestTop, MidChestCenter, MidChestBottom, BelowChest, na.rm = TRUE),
         fcr = (face - chest) / (face + chest))
# Table of means
babies_fcr %>% 
  group_by(lang, direction, name) %>%
  summarise(fcr = mean(fcr)) %>% # gets average looking percent for each baby
  group_by(lang, direction) %>%
  summarise(mean_fcr = mean(fcr), # gets group averages
            count = n(),
            sd = sd(fcr),
            se = sd/sqrt(count)) %>%
  select(-sd) %>%
  print()
# Plot
ggplot(babies_fcr, aes(x = age, y = fcr, color = direction, fill = direction)) + 
  geom_jitter(alpha = 0.5) + 
  geom_smooth(method = "lm", se = FALSE) +
  scale_y_continuous(limits = c(-1,1)) +
  theme_bw() + 
  theme(panel.grid.major.x = element_blank()) +
  facet_grid(. ~ lang) +
  ggtitle("Face-Chest Ratios") +
  xlab("") +
  ylab("FCR")

# Bar chart
# babies_fcr %>% 
#   group_by(agegroup, lang, direction, name) %>%
#   summarise(fcr = mean(fcr)) %>% # gets average looking percent for each baby
#   group_by(agegroup, lang, direction) %>%
#   summarise(mean_fcr = mean(fcr), # gets group averages
#             count = n(),
#             sd = sd(fcr),
#             se = sd/sqrt(count)) %>% 
#   ggplot(aes(x = lang, y = mean_fcr, fill = direction)) + 
#   geom_col(position = "dodge") + 
#   geom_errorbar(aes(ymin = mean_fcr - se, ymax = mean_fcr + se), 
#                 position = position_dodge(width = 0.9), width = 0.25) + 
#   scale_y_continuous(limits = c(-1,1)) +
#   theme_minimal() + 
#   theme(panel.grid.major.x = element_blank()) +
#   facet_wrap("agegroup") +
#   ggtitle("Face-Chest Ratios") +
#   xlab("") +
#   ylab("FCR")

What will a linear mixed model tell us? (with no age interactions)

  • No effect of age. Interesting. Maybe because we don’t have that many babies.
  • Strong effect of language: SE babies have overall +0.50 FCR than NSE babies (p = 0.008); in other words, they are more attracted to the face.
  • Effect of direction: Reversal increases FCR by +0.12 across all babies (p = 0.032). Interesting.
  • Weak language x direction interaction. It seems NSE babies have a bigger reversal effect than SE babies? Trying to judge from the heat maps. (p = 0.095). BUt it’s so weak so possibly not worth mentioning.
fcr_lm <- lmer(fcr ~ age + lang * direction + (1|name) + (1|story), data = babies_fcr)
summary(fcr_lm)
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: fcr ~ age + lang * direction + (1 | name) + (1 | story)
   Data: babies_fcr

REML criterion at convergence: 435.5

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-2.2135 -0.7622  0.1098  0.6343  2.3489 

Random effects:
 Groups   Name        Variance Std.Dev.
 name     (Intercept) 0.14776  0.3844  
 story    (Intercept) 0.01342  0.1158  
 Residual             0.15708  0.3963  
Number of obs: 349, groups:  name, 26; story, 8

Fixed effects:
                          Estimate Std. Error        df t value Pr(>|t|)  
(Intercept)                0.07490    0.26654  24.59417   0.281   0.7811  
age                       -0.04443    0.02930  22.87598  -1.516   0.1431  
langSE                     0.45427    0.16972  25.84156   2.677   0.0127 *
directionreversed          0.11887    0.05605 316.96084   2.121   0.0347 *
langSE:directionreversed  -0.14367    0.08683 315.78391  -1.655   0.0990 .
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) age    langSE drctnr
age         -0.908                     
langSE      -0.060 -0.196              
dirctnrvrsd -0.098 -0.002  0.158       
lngSE:drctn  0.060  0.005 -0.249 -0.647
#ggcoef(fcr_lm)

Heat Maps

And now heat maps!

heatmap_babies <- babies %>%
  filter(aoi %in% midline) %>%
  ungroup() %>%
  group_by(lang, name, direction, aoi) %>%
  summarise(percent = mean(percent, na.rm=TRUE)) %>%
  group_by(lang, direction, aoi) %>%
  summarise(percent = mean(percent, na.rm=TRUE)) %>%
  ungroup() %>%
  mutate(aoi = factor(aoi, levels = c("Belly","BelowChest","MidChestBottom","MidChestCenter","MidChestTop",
            "MidFaceBottom","MidFaceCenter","MidFaceTop")))
ggplot(heatmap_babies, aes(x = lang, y = aoi)) +
  geom_tile(aes(fill=percent),color="lightgray",na.rm=TRUE) + 
#  scale_fill_viridis(option = "viridis", direction=-1, limits = c(0,.7), labels = percent, name = "looking time") +
    scale_fill_gradient(low = "#ffffff", high = "#08519c", space = "Lab", limits = c(0,.451), labels = percent, name = "looking time", na.value = "grey50") +
  theme_bw() +
  theme(strip.text.x = element_text(size = 11, color = "black", face = "italic"), 
        strip.background = element_rect(colour = "white", fill = "white"),
        panel.grid.major = element_line(color = "white")) +
  facet_grid(. ~ direction) +
  ylab("") + xlab("") + ggtitle("Eye Gaze Heat Map, by Direction") + 
  scale_y_discrete(expand=c(0,0)) +
  scale_x_discrete(expand = c(0,0))

ggplot(heatmap_babies, aes(x = direction, y = aoi)) +
  geom_tile(aes(fill=percent),color="lightgray",na.rm=TRUE) + 
#  scale_fill_viridis(option = "viridis", direction=-1, limits = c(0,.7), labels = percent, name = "looking time") +
    scale_fill_gradient(low = "#ffffff", high = "#08519c", space = "Lab", limits = c(0,.451), labels = percent, name = "looking time", na.value = "grey50") +
  theme_bw() +
  theme(strip.text.x = element_text(size = 11, color = "black", face = "italic"), 
        strip.background = element_rect(colour = "white", fill = "white"),
        panel.grid.major = element_line(color = "white")) +
  facet_grid(. ~ lang) +
  ylab("") + xlab("") + ggtitle("Eye Gaze Heat Map, by Language") + 
  scale_y_discrete(expand=c(0,0)) +
  scale_x_discrete(expand = c(0,0))

Different Ways to Visualize Reversal

I want to try to visualize reversal effects a different way. Maybe this.

# Get participant-level data
babies_fcr2 <- babies_fcr %>%
  group_by(name, age, lang, direction) %>%
  summarise(fcr = mean(fcr))
# reversal_effect_lm <- lmer(fcr ~ age + lang * direction + (1|name), data = babies_fcr2)
# summary(reversal_effect_lm)
ggplot(babies_fcr2, aes(x = direction, y = fcr, color = lang, fill = lang)) +
  geom_point() +
  geom_line(aes(group = name)) +
  facet_grid(. ~ lang) + 
  scale_y_continuous(limits = c(-1,1)) +
  theme_bw()

Or a reversal effect chart? Okay, so this chart tells us overall there really wasn’t much of a reversal effect for SE babies, they’re all hovering around 0. Interesting. While there seems to be a reversal effect for NSE babies where they look at the face more during reversed stories!

# Get participant-level data
babies_fcr3 <- babies_fcr2 %>%
  spread(direction, fcr) %>%
  group_by(name, age, lang) %>%
  summarise(diff = forward - reversed)
ggplot(babies_fcr3, aes(x = age, y = diff, color = lang)) +
  geom_point() +
  geom_smooth(method = "lm", se = FALSE) +
  scale_y_continuous(limits = c(-1,1)) +
  theme_bw() +
  ggtitle("Reversal Effect") +
  ylab("Forward FCR - Reversed FCR")

This analysis of within-subject variation here:

# First get the mean of each trial, THEN the participant-level means
within_subjects <- babies_fcr %>%
  group_by(name, lang, direction, story, repetition) %>%
  summarise(fcr = mean(fcr, na.rm = TRUE),
            count = n()) %>%
  group_by(name, lang, direction) %>%
  summarise(mean = mean(fcr, na.rm = TRUE),
            se = sd(fcr, na.rm = TRUE)/sqrt(n()),
            count = n())
# Then spread out mean and SE columns by direction
within_subjects_means <- within_subjects %>%
  select(-se, -count) %>%
  spread(direction, mean, sep = "_")
within_subjects_se <- within_subjects %>%
  select(-mean, -count) %>%
  spread(direction, se, sep = "SE")
within_subjects <- left_join(within_subjects_means, within_subjects_se, by = c("name","lang"))
# Now let's plot
lims <- c(-1,1)
within_subjects %>%
  ggplot(aes(x = direction_forward, y = direction_reversed, color = lang)) +
  geom_abline() +
  geom_point(size = 2) + 
  geom_errorbar(aes(ymin=direction_reversed-directionSEreversed, ymax=direction_reversed+directionSEreversed)) +
  geom_errorbarh(aes(xmin=direction_forward-directionSEforward, xmax=direction_forward+directionSEforward)) +
  theme_bw() +
  theme(aspect.ratio = 1) +
  scale_x_continuous("forward", limits = c(-1,1)) +
  scale_y_continuous("reversed", limits = c(-1,1)) +
  ggtitle("FCR Means") +
  facet_wrap("lang")

And a classic box/error plot with age collapsed.

babies_fcr2 %>%
  group_by(lang, direction) %>%
  summarise(fcr_mean = mean(fcr),
            sd = sd(fcr),
            n = n(),
            se = sd/sqrt(n)) %>%
  ggplot(aes(x = lang, y = fcr_mean, fill = direction)) +
  geom_bar(stat = "identity", position = position_dodge()) + 
  geom_errorbar(aes(ymin = fcr_mean-se, ymax = fcr_mean+se), position = position_dodge(0.9), width = 0.2) +
  scale_y_continuous(limits = c(-0.5, 0.5)) +
  theme_linedraw()

Discussion re AOI/anatomical data

The biggest change is we lost the interaction between language and direction. For the ICSLA abstract we reported a strong interaction (p = 0.01), but now it’s p = 0.10. Shoot.

The interpretation here is that:

  • All babies looked equally at all videos regardless of language or direction. Good!
  • SE babies are stronger face-lookers than NSE babies. (Same as ICSLA)
  • Reversal appears to affect NSE babies more than SE babies? (Marginal). This is unlike ICSLA.

XY Space Data

We’ll load the data from the childxydata.feather file made in 06rawxydata.Rmd. So any new babies, please run the first code block in 06 to include it. Then we’ll keep all the babies we also have in the AOI data group.

included <- babies %>%
  ungroup() %>%
  select(name) %>% 
  distinct() %>%
  unlist()
xydata <- read_feather("../Child Data/childxydata.feather") %>%
  rename(name = participant) %>%
  filter(name %in% included)
# Get ages
ages <- read_csv("childrenages.csv") %>%
  rename(name = participant)
xydata <- xydata %>% left_join(ages, by = "name") %>%
  mutate(age = age*12) %>%
  mutate(agegroup = case_when(
    age <= 8.99 ~ "younger",
    age >= 9.0 & age < 15 ~ "older"
  )) %>%
  mutate(language = case_when(
    language == "EnglishExposed" ~ "NSE",
    language == "SignLanguageExposed" ~ "SE"
  )) %>%
  rename(lang = language) %>%
  select(name, group, gender, lang, condition, mark, trial, repetition, x, y, age, agegroup) %>%
  separate(condition, into = c("story", "clip", "direction")) %>%
  unite("story", c("story", "clip")) %>%
  mutate(direction = case_when(
    direction == "ER" ~ "reversed",
    direction == "FW" ~ "forward"
  )) %>%
  mutate(name = factor(name),
         group = factor(group),
         gender = factor(gender),
         lang = factor(lang),
         story = factor(story),
         direction = factor(direction),
         mark = factor(mark),
         trial = factor(trial),
         repetition = factor(repetition),
         agegroup = factor(agegroup))

Overall Looking

Let’s check that we have no significant group or condition differences in terms of valid (not empty) data points collected. This is same as “Global Looking” we have above, really, but w raw xy data.

xy_overall <- xydata %>%
  filter(!is.na(x)) %>%
  group_by(name, age, lang, direction, story, repetition) %>%
  summarise(data_points = n()) # gets total looking percent for each trial for each baby
# Table of means
xy_overall %>% 
  group_by(name, lang, direction) %>%
  summarise(data_points = mean(data_points)) %>% # get average looking percent for each baby
  group_by(lang, direction) %>%
  summarise(mean_data_points = mean(data_points),
            count = n(),
            sd = sd(data_points),
            se = sd/sqrt(count)) %>%
  select(-sd) %>%
  print()
ggplot(xy_overall, aes(x = age, y = data_points, color = direction, fill = direction)) + 
  geom_jitter(alpha = 0.5) +
  facet_grid(. ~ lang) +
  geom_smooth(method = "lm", se = FALSE) +
  ggtitle("Data Points") +
  xlab("age (months)") +
  ylab("data points recorded") + 
  theme_bw() 

A linear model shows there were no significant effects of any factors. We can conclude there was no effect on how much data was collected from the babies.

overall_xy_lm <- lmer(data_points ~ age + lang * direction + (direction|name) + (direction|story), data = xy_overall)
summary(overall_xy_lm) 
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: data_points ~ age + lang * direction + (direction | name) + (direction |      story)
   Data: xy_overall

REML criterion at convergence: 5528.3

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-3.7588 -0.6663 -0.0078  0.6278  2.5542 

Random effects:
 Groups   Name              Variance Std.Dev. Corr 
 name     (Intercept)       20748.3  144.04        
          directionreversed   827.6   28.77   1.00 
 story    (Intercept)       22549.1  150.16        
          directionreversed  4215.1   64.92   -0.05
 Residual                   52385.3  228.88        
Number of obs: 401, groups:  name, 26; story, 8

Fixed effects:
                         Estimate Std. Error      df t value Pr(>|t|)    
(Intercept)               524.548    120.054  29.519   4.369 0.000141 ***
age                         8.531     12.060  23.322   0.707 0.486339    
langSE                      8.304     68.321  23.886   0.122 0.904275    
directionreversed         -20.437     38.068  11.693  -0.537 0.601428    
langSE:directionreversed  -16.638     48.592 131.756  -0.342 0.732595    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) age    langSE drctnr
age         -0.828                     
langSE      -0.040 -0.204              
dirctnrvrsd -0.045 -0.003  0.063       
lngSE:drctn  0.026  0.002 -0.130 -0.499
#ggcoef(overall_xy_lm)

XY Data LMMs

Now we’re going to run LMMs on babies’ raw:

  • horizontal spread (middle 50% of x data; xIQR)
  • vertical spread (middle 50% of y data; yIQR)
  • viewing area (A = middle-x * middle-y; area)

But to do this we first trim each baby’s data, getting rid of the first 60 samples (0.5 secs) of each trial.

xydata <- xydata %>%
  group_by(name,trial) %>%
  slice(60:n())
iqr <- xydata %>%
  group_by(name, age, lang, story, direction, trial) %>%
  summarise(xIQR = IQR(x,na.rm=TRUE),
                   yIQR = IQR(y,na.rm=TRUE),
                   xmed = median(x, na.rm=TRUE),
                   ymed = median(y, na.rm=TRUE),
                   area = xIQR*yIQR)
head(iqr,20)

Middle X

Results tell us that there is a significant effect of age where horizontal spread grew narrower with older babies (p = 0.024; slope = -2.2 px/month). There was a marginal effect of language where SE babies have slightly narrower horizontal spread (11 px; p = 0.088). No effects of reversal or interactions.

xiqr_mean <- iqr %>% 
  group_by(lang, direction, name) %>%
  summarise(xIQR = mean(xIQR, na.rm = T)) %>% # gets average looking percent for each baby
  group_by(lang, direction) %>%
  summarise(mean_xIQR = mean(xIQR), # gets group averages
            count = n(),
            sd = sd(xIQR),
            se = sd/sqrt(count)) %>%
  select(-sd) %>%
  print()
# Plot
ggplot(iqr, aes(x = age, y = xIQR, color = direction, fill = direction)) + 
  geom_jitter(alpha = 0.5) + 
  geom_smooth(method = "lm", se = FALSE) +
  theme_bw() + 
  theme(panel.grid.major.x = element_blank()) +
  facet_grid(. ~ lang) +
  ggtitle("Horizontal Spread") +
  xlab("") +
  ylab("xIQR")

ggplot(xiqr_mean, aes(x = lang, y = mean_xIQR, fill = direction)) +
  geom_bar(stat = "identity", position = position_dodge()) + 
  geom_errorbar(aes(ymin = mean_xIQR-se, ymax = mean_xIQR+se), position = position_dodge(0.9), width = 0.2) +
  theme_linedraw()

xiqr_lm <- lmer(xIQR ~ age + lang * direction + (1|name) + (1|story), data = iqr)
summary(xiqr_lm)
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: xIQR ~ age + lang * direction + (1 | name) + (1 | story)
   Data: iqr

REML criterion at convergence: 3839.2

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-2.1407 -0.4782 -0.1683  0.2668  9.8629 

Random effects:
 Groups   Name        Variance Std.Dev.
 name     (Intercept) 104.0925 10.2026 
 story    (Intercept)   0.4767  0.6905 
 Residual             901.8472 30.0308 
Number of obs: 398, groups:  name, 26; story, 8

Fixed effects:
                         Estimate Std. Error       df t value Pr(>|t|)    
(Intercept)               63.5887     8.5596  25.6516   7.429  7.5e-08 ***
age                       -2.2423     0.9342  23.2148  -2.400   0.0248 *  
langSE                   -12.0971     6.0828  41.5383  -1.989   0.0533 .  
directionreversed          1.9022     3.8627 372.0710   0.492   0.6227    
langSE:directionreversed   0.1790     6.1817 369.3456   0.029   0.9769    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) age    langSE drctnr
age         -0.901                     
langSE      -0.106 -0.175              
dirctnrvrsd -0.213 -0.006  0.308       
lngSE:drctn  0.135  0.002 -0.504 -0.625
#ggcoef(xiqr_lm)

Middle Y

We had a significant effect of age where vertical spread got narrower with older babies (p = 0.019, slope = -5.5 px/month). There were no effect of language, direction, or interactions.

yiqr_mean <- iqr %>% 
  group_by(lang, direction, name) %>%
  summarise(yIQR = mean(yIQR, na.rm = T)) %>% # gets average looking percent for each baby
  group_by(lang, direction) %>%
  summarise(mean_yIQR = mean(yIQR), # gets group averages
            count = n(),
            sd = sd(yIQR),
            se = sd/sqrt(count)) %>%
  select(-sd) %>%
  print()
# Plot
ggplot(iqr, aes(x = age, y = yIQR, color = direction, fill = direction)) + 
  geom_jitter(alpha = 0.5) + 
  geom_smooth(method = "lm", se = FALSE) +
  theme_bw() + 
  theme(panel.grid.major.x = element_blank()) +
  facet_grid(. ~ lang) +
  ggtitle("Vertical Spread") +
  xlab("") +
  ylab("yIQR")

ggplot(yiqr_mean, aes(x = lang, y = mean_yIQR, fill = direction)) +
  geom_bar(stat = "identity", position = position_dodge()) + 
  geom_errorbar(aes(ymin = mean_yIQR-se, ymax = mean_yIQR+se), position = position_dodge(0.9), width = 0.2) +
  theme_linedraw()

yiqr_lm <- lmer(yIQR ~ age + lang * direction + (1|name) + (1|story), data = iqr)
summary(yiqr_lm)
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: yIQR ~ age + lang * direction + (1 | name) + (1 | story)
   Data: iqr

REML criterion at convergence: 4251.3

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-2.7516 -0.5310 -0.2210  0.3696  5.8948 

Random effects:
 Groups   Name        Variance  Std.Dev. 
 name     (Intercept) 6.890e+02 2.625e+01
 story    (Intercept) 7.045e-12 2.654e-06
 Residual             2.480e+03 4.979e+01
Number of obs: 398, groups:  name, 26; story, 8

Fixed effects:
                         Estimate Std. Error      df t value Pr(>|t|)    
(Intercept)               119.653     19.332  24.309   6.189 2.03e-06 ***
age                        -5.506      2.136  23.024  -2.578   0.0168 *  
langSE                    -16.804     13.040  32.003  -1.289   0.2068    
directionreversed           8.778      6.407 371.087   1.370   0.1715    
langSE:directionreversed   -5.713     10.252 370.630  -0.557   0.5777    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) age    langSE drctnr
age         -0.912                     
langSE      -0.079 -0.187              
dirctnrvrsd -0.156 -0.005  0.238       
lngSE:drctn  0.099  0.001 -0.390 -0.625
#ggcoef(yiqr_lm)

Viewing Area

Again, age is significant (p = 0.01) such that area gets smaller with age (about 500 sq. px. per month). No effect of language or direction or interactions.

area_mean <- iqr %>% 
  group_by(lang, direction, name) %>%
  summarise(area = mean(area, na.rm = T)) %>% # gets average looking percent for each baby
  group_by(lang, direction) %>%
  summarise(area_mean = mean(area), # gets group averages
            count = n(),
            sd = sd(area),
            se = sd/sqrt(count)) %>%
  select(-sd) %>%
  print()
# Plot
ggplot(iqr, aes(x = age, y = area, color = direction, fill = direction)) + 
  geom_jitter(alpha = 0.5) + 
  geom_smooth(method = "lm", se = FALSE) +
  theme_bw() + 
  theme(panel.grid.major.x = element_blank()) +
  facet_grid(. ~ lang) +
  ggtitle("Viewing Area") +
  xlab("") +
  ylab("Area (px^2)")

ggplot(area_mean, aes(x = lang, y = area_mean, fill = direction)) +
  geom_bar(stat = "identity", position = position_dodge()) + 
  geom_errorbar(aes(ymin = area_mean-se, ymax = area_mean+se), position = position_dodge(0.9), width = 0.2) +
  theme_linedraw()

area_lm <- lmer(area ~ age + lang * direction + (1|name) + (1|story), data = iqr)
summary(area_lm)
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: area ~ age + lang * direction + (1 | name) + (1 | story)
   Data: iqr

REML criterion at convergence: 8154.5

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-1.6788 -0.2727 -0.1278  0.0299 13.4544 

Random effects:
 Groups   Name        Variance  Std.Dev. 
 name     (Intercept) 6.231e+06 2.496e+03
 story    (Intercept) 4.677e-10 2.163e-05
 Residual             5.292e+07 7.275e+03
Number of obs: 398, groups:  name, 26; story, 8

Fixed effects:
                         Estimate Std. Error       df t value Pr(>|t|)    
(Intercept)               9372.80    2085.26    25.71   4.495  0.00013 ***
age                       -589.26     227.76    23.24  -2.587  0.01640 *  
langSE                   -2048.69    1480.52    41.32  -1.384  0.17386    
directionreversed          712.93     935.49   372.10   0.762  0.44648    
langSE:directionreversed  -303.67    1497.33   371.32  -0.203  0.83940    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) age    langSE drctnr
age         -0.902                     
langSE      -0.105 -0.176              
dirctnrvrsd -0.211 -0.006  0.307       
lngSE:drctn  0.134  0.002 -0.502 -0.625
#ggcoef(area_lm)

Plotting Viewing Area

medians <- iqr %>%
  group_by(name,lang,direction) %>%
  summarise(xIQR = median(xIQR,na.rm=TRUE),
                   yIQR = median(yIQR,na.rm=TRUE),
                   xmed = median(xmed,na.rm=TRUE),
                   ymed = median(ymed,na.rm=TRUE)) %>%
  group_by(lang,direction) %>% 
  summarise(xIQR = mean(xIQR,na.rm=TRUE),
                   yIQR = mean(yIQR,na.rm=TRUE),
                   x = median(xmed,na.rm=TRUE),
                   y = median(ymed,na.rm=TRUE)) %>%
  mutate(y = y*-1,
         xmin = x-(xIQR/2),
         xmax = x+(xIQR/2),
         ymin = y-(yIQR/2),
         ymax = y+(yIQR/2))
img <- png::readPNG("cindy.png")
g <- grid::rasterGrob(img, interpolate=TRUE, width=unit(1,"npc"), height=unit(1,"npc")) 
ggplot(medians, aes(fill=direction,color=direction)) +
  annotation_custom(g, xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf) +
  geom_rect(aes(xmin=xmin,ymin=ymin,xmax=xmax,ymax=ymax),alpha=.1) + 
  theme_linedraw() +
  scale_x_continuous(limits = c(0,1080), expand = c(0, 0)) +
  scale_y_continuous(limits = c(-720,0), expand = c(0, 0)) +
  facet_wrap("lang")

Puppies

Get puppy data!

# puppies1 <- read_tsv("../Child Data/_puppies/all puppies group 1 sums.txt", na = "-") %>% 
#   clean_names() %>%
#   select(-c(age, analysis, check_if_want_scatterplot, gender, language)) %>%
#   rename(name = x1) %>%
#   mutate(mean = rowMeans(.[2:10], na.rm = T)) %>%
#   select(name, mean)
#   
# puppies2 <- read_tsv("../Child Data/_puppies/all puppies group 2 sums.txt", na = "-") %>% 
#   clean_names() %>%
#   select(-c(age, analysis, check_if_want_scatterplot, gender, language)) %>%
#   rename(name = x1) %>%
#   mutate(mean = rowMeans(.[2:17], na.rm = T)) %>%
#   select(name, mean)
# 
# puppies <- rbind(puppies1, puppies2)
# 
# participants <- xydata %>% 
#   select(name, group, gender, lang) %>% 
#   distinct()
# 
# puppies <- left_join(participants, puppies, by = "name")
# 
# summary(lm(data = puppies, mean ~ lang))
# 
# puppies_se <- filter(puppies, lang == "NSE")
# puppies_nse <- filter(puppies, lang == "SE")
# 
# t.test(puppies_se$mean, puppies_nse$mean)
# Let's do this again but preserve puppy-level data
puppies1 <- read_tsv("../Child Data/_puppies/all puppies group 1 sums.txt", na = "-") %>% 
  clean_names() %>%
  select(-c(age, analysis, check_if_want_scatterplot, gender, language)) %>%
  rename(name = x1) %>%
  gather(key = puppy, value = sec, -name) %>%
  mutate(pups = case_when(
    str_detect(puppy, "huskies") ~ "huskies",
    str_detect(puppy, "golden") ~ "golden",
    str_detect(puppy, "wawa") ~ "wawa",
    str_detect(puppy, "frisby") ~ "frisby",
    str_detect(puppy, "bulldog") ~ "bulldog",
    str_detect(puppy, "puppy_jpg") ~ "puppy",
    TRUE ~ puppy
  ))
puppies2 <- read_tsv("../Child Data/_puppies/all puppies group 2 sums.txt", na = "-") %>% 
  clean_names() %>%
  select(-c(age, analysis, check_if_want_scatterplot, gender, language)) %>%
  rename(name = x1) %>%
  gather(key = puppy, value = sec, -name) %>%
  mutate(pups = case_when(
    str_detect(puppy, "huskies") ~ "huskies",
    str_detect(puppy, "golden") ~ "golden",
    str_detect(puppy, "wawa") ~ "wawa",
    str_detect(puppy, "frisby") ~ "frisby",
    str_detect(puppy, "bulldog") ~ "bulldog",
    str_detect(puppy, "puppies") ~ "puppies",
    TRUE ~ puppy
  ))
puppies <- rbind(puppies1,puppies2)
participants <- xydata %>%
  select(name, group, gender, lang) %>%
  distinct()
puppies <- left_join(participants, puppies, by = "name")
summary(lmer(data = puppies, sec ~ lang + (1|name) + (1|pups)))
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: sec ~ lang + (1 | name) + (1 | pups)
   Data: puppies

REML criterion at convergence: 15818.6

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-2.9738 -0.5348 -0.0747  0.3391  8.2862 

Random effects:
 Groups   Name        Variance Std.Dev.
 name     (Intercept) 0.8587   0.9267  
 pups     (Intercept) 0.1115   0.3339  
 Residual             1.8390   1.3561  
Number of obs: 4550, groups:  name, 26; pups, 7

Fixed effects:
            Estimate Std. Error      df t value Pr(>|t|)    
(Intercept)   2.1716     0.2655 29.2732   8.178 4.76e-09 ***
langSE       -0.5248     0.3759 23.9367  -1.396    0.176    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
       (Intr)
langSE -0.545
ggplot(puppies, aes(x = lang, y = sec, fill = lang)) + geom_boxplot()

LS0tCnRpdGxlOiAiQmFiaWVzIC0gU3R1ZHkgMiAtIFJlc3VsdHMiCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdGhlbWU6IHNwYWNlbGFiCiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiAyCiAgICB0b2NfZmxvYXQ6IHllcwogICAgZGZfcHJpbnQ6IHBhZ2VkCi0tLQoKVGhpcyBpcyBob3BlZnVsbHkgdGhlIHJlc3VsdHMgc2VjdGlvbiBmb3IgdGhlIFN0dWR5IDIgTlNFICYgU0UgYmFiaWVzIHdhdGNoaW5nIEFTTCBTdG9yaWVzLiBXZSBoYXZlIHR3byBtYWluIGZhY3RvcnM6IAoKMS4gTGFuZ3VhZ2UgKFNpZ24gdi4gRW5nbGlzaCkKMS4gRGlyZWN0aW9uIChGb3J3YXJkIHYuIFJldmVyc2VkKQoKQWdlcyBvZiBiYWJpZXMgYXJlIGZyb20gNSB0byAxNC45OSBtb250aHMuIFRoYXQgbWVhbnMgd2UgbG9zZSB0d28gIm9sZCIgQ09EQSBiYWJpZXMgLSBKYW5pbmUgKDE2IG1vKSBhbmQgemEwMiAoMjMgbW8pLiBUaGUgZGF0YXNldCBhbHNvIGNvbnRhaW5zIGZhY3RvcnMgZm9yIHlvdW5nZXIgdi4gb2xkZXIgYmFiaWVzICpJRiogd2Ugd2FudCB0byBkbyBhZ2UgZ3JvdXAgc3BsaXRzLiBJIGRvIG5vdCByZWNvbW1lbmQgaXQgYmVjYXVzZSB3ZSBsb3NlIGFsbCBzaWduaWZpY2FuY2UgdGhhdCB3YXkgYW5kIHdlIGhhdmUgbW9yZSBwcmVjaXNlIGFnZSBpbmZvcm1hdGlvbiwgYmV0dGVyIHRoYW4gYnJ1dGUgZ3JvdXBzLiAgSUYgd2UgZG8gdXNlIGl0LCB0aGUgYmFieSBhZ2UgZ3JvdXBzIGFyZSBzdWNoOgoKKiBZb3VuZ2VyIGJhYmllcyA9IDUgdG8gOC45OSBtb250aHMKKiBPbGRlciBiYWJpZXMgPSA5LjAgdG8gMTQuOTkgbW9udGhzCgpUbyBza2lwIHRvIHRoZSBYWSBEYXRhLCBnbyBoZXJlLiAKVG8gc2tpcCB0byB0aGUgQU9JL0ZDUiBhbmFseXNpcywgZ28gaGVyZS4gCgojIERlbW9ncmFwaGljcwpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShqYW5pdG9yKQpsaWJyYXJ5KGxtZTQpCmxpYnJhcnkobG1lclRlc3QpCmxpYnJhcnkoc2NhbGVzKQpsaWJyYXJ5KGZlYXRoZXIpCmxpYnJhcnkoR0dhbGx5KQoKIyBHcmFiIGRhdGEgdGhhdCB3YXMgcHJvZHVjZWQgaW4gMDNpbXBvcnRjbGVhbmJhYmllcy5SbWQKYmFiaWVzIDwtIHJlYWRfZmVhdGhlcigiY2xlYW5lZGJhYnlleWVkYXRhLmZlYXRoZXIiKSAlPiUKICBtdXRhdGUoYWdlID0gYWdlKjEyKSAlPiUKICBzZWxlY3QocGFydGljaXBhbnQsIGxhbmd1YWdlLCBhZ2UsIGdlbmRlciwgc3RvcnksIGRpcmVjdGlvbiwgbWFyaywgdHJpYWwsIHJlcGV0aXRpb24sIGFvaSwgc2VjcywgcGVyY2VudCkgJT4lCiAgcmVuYW1lKG5hbWUgPSBwYXJ0aWNpcGFudCkgJT4lCiAgbXV0YXRlKGFnZWdyb3VwID0gY2FzZV93aGVuKAogICAgYWdlIDw9IDguOTkgfiAieW91bmdlciIsCiAgICBhZ2UgPj0gOS4wICYgYWdlIDwgMTUgfiAib2xkZXIiCiAgKSkgJT4lCiAgZmlsdGVyKCFpcy5uYShhZ2Vncm91cCkpICU+JQogIG11dGF0ZShsYW5ndWFnZSA9IGNhc2Vfd2hlbigKICAgIGxhbmd1YWdlID09ICJlbmdsaXNoIiB+ICJOU0UiLAogICAgbGFuZ3VhZ2UgPT0ic2lnbiIgfiAiU0UiCiAgKSkgJT4lCiAgcmVuYW1lKGxhbmcgPSBsYW5ndWFnZSkgJT4lCiAgbXV0YXRlKGxhbmcyID0gY2FzZV93aGVuKAogICAgbmFtZSA9PSAiYXVicmV5IENPREEgMTFtIiB+ICJIU0UiLAogICAgbmFtZSA9PSAiR2VtbWFGXzExXzRfMTNfQ09EQSIgfiAiSFNFIiwKICAgIG5hbWUgPT0gIkhhbm5haF9DT0RBXzdtIiB+ICJIU0UiLAogICAgbmFtZSA9PSAia2UxMWVzMTJfN21fTW9tVGVycCIgfiAiTFNFIiwKICAgIG5hbWUgPT0gIk1pbGVzXzE0bV9TRSIgfiAiSFNFIiwKICAgIG5hbWUgPT0gIlBhcmtlciA2IG0gU0lHTklORyIgfiAiSFNFIiwKICAgIG5hbWUgPT0gIlBlbm4gNiBtb250aHMgU0lHTiBFWFBPU0VEIiB+ICJIU0UiLAogICAgbmFtZSA9PSAiVHJpbml0eSA4bSIgfiAiTFNFIiwKICAgIG5hbWUgPT0gIlZpY3RvcmlhMDdfMThfMTciIH4gIkxTRSIsCiAgICBuYW1lID09ICJXZWxsc184bW9zIiB+ICJMU0UiLAogICAgVFJVRSB+IGxhbmcKICApKQojICBmaWx0ZXIobmFtZSAhPSAiVmljdG9yaWEwN18xOF8xNyIpCgpiYWJpZXNpbmZvIDwtIGJhYmllcyAlPiUKICBzZWxlY3QobmFtZSwgbGFuZywgYWdlLCBnZW5kZXIpICU+JQogIGRpc3RpbmN0KCkgJT4lCiAgZ3JvdXBfYnkobGFuZykgJT4lCiAgc3VtbWFyaXNlKE4gPSBuKCksCiAgICAgICAgICAgIGFnZV9tZWFuID0gbWVhbihhZ2UpLAogICAgICAgICAgICBzZCA9IHNkKGFnZSksCiAgICAgICAgICAgIG1pbiA9IG1pbihhZ2UpLAogICAgICAgICAgICBtYXggPSBtYXgoYWdlKSkKCmdlbmRlcnMgPC0gYmFiaWVzICU+JQogIHNlbGVjdChuYW1lLCBsYW5nLCBhZ2UsIGdlbmRlcikgJT4lCiAgZGlzdGluY3QoKSAlPiUKICBncm91cF9ieShsYW5nLCBnZW5kZXIpICU+JQogIHN1bW1hcmlzZShOID0gbigpKSAlPiUKICBzcHJlYWQoZ2VuZGVyLCBOKQoKYmFiaWVzaW5mbyA8LSBsZWZ0X2pvaW4oYmFiaWVzaW5mbywgZ2VuZGVycykgJT4lCiAgc2VsZWN0KGxhbmcsIE4sIEZlbWFsZSwgTWFsZSwgYWdlX21lYW4sIHNkLCBtaW4sIG1heCkgJT4lCiAgcHJpbnQoKQoKYmFiaWVzJGFnZWdyb3VwIDwtIGZjdF9yZWxldmVsKGJhYmllcyRhZ2Vncm91cCwgYygieW91bmdlciIsIm9sZGVyIikpCgoKIyBJRiB3ZSBkbyBhZ2UgZ3JvdXBzLCB1c2UgdGhpcyBjb2RlCiMgCiMgYmFiaWVzaW5mbyA8LSBiYWJpZXMgJT4lCiMgICBzZWxlY3QobmFtZSwgbGFuZywgYWdlLCBhZ2Vncm91cCwgZ2VuZGVyKSAlPiUKIyAgIGRpc3RpbmN0KCkgJT4lCiMgICBncm91cF9ieShsYW5nLCBhZ2Vncm91cCkgJT4lCiMgICBzdW1tYXJpc2UoTiA9IG4oKSwKIyAgICAgICAgICAgICBhZ2VfbWVhbiA9IG1lYW4oYWdlKSwKIyAgICAgICAgICAgICBzZCA9IHNkKGFnZSksCiMgICAgICAgICAgICAgbWluID0gbWluKGFnZSksCiMgICAgICAgICAgICAgbWF4ID0gbWF4KGFnZSkpCiMgCiMgZ2VuZGVycyA8LSBiYWJpZXMgJT4lCiMgICBzZWxlY3QobmFtZSwgbGFuZywgYWdlLCBhZ2Vncm91cCwgZ2VuZGVyKSAlPiUKIyAgIGRpc3RpbmN0KCkgJT4lCiMgICBncm91cF9ieShsYW5nLCBhZ2Vncm91cCwgZ2VuZGVyKSAlPiUKIyAgIHN1bW1hcmlzZShOID0gbigpKSAlPiUKIyAgIHNwcmVhZChnZW5kZXIsIE4pCiMgCiMgYmFiaWVzaW5mbyA8LSBsZWZ0X2pvaW4oYmFiaWVzaW5mbywgZ2VuZGVycykgJT4lCiMgICBzZWxlY3QobGFuZywgYWdlZ3JvdXAsIE4sIEZlbWFsZSwgTWFsZSwgYWdlX21lYW4sIHNkLCBtaW4sIG1heCkgJT4lCiMgICBwcmludCgpCgpgYGAKCiMgR2xvYmFsIExvb2tpbmcKCldlIGNhbGN1bGF0ZWQgcGVyY2VudGFnZXMgKmJhc2VkIG9uIG92ZXJhbGwgY2xpcCBsZW5ndGgqIGFzIHRoZSBkZW5vbWluYXRvci4gSW4gdGhpcyB3YXksIHdlIGNhbiBtZWFuaW5nZnVsbHkgY29udHJhc3QgbG9va2luZyB0aW1lcyBhdCB0aGUgdmlkZW9zICh3aGljaCBhcmUgdmFyaWFibGUgbGVuZ3RocykgYmFzZWQgb24gZGlmZmVyZW50IGZhY3RvcnMuIEJ1dCB3aGVuIHdlIGdvIHRvIEFPSSBhbmFseXNpcyB3ZSBuZWVkIHRvIHJlLWNhbGN1bGF0ZSB0aGUgcGVyY2VudGFnZXMgc28gdGhlIGRlbm9taW5hdG9yIGlzIGJhc2VkIG9uIHRvdGFsIGxvb2tpbmcgdGltZSwgbm90IG92ZXJhbGwgY2xpcCBsZW5ndGguIAoKVGhlIGNoYXJ0IGJlbG93IHNob3dzIGxpdHRsZSBkaWZmZXJlbmNlcyBiYXNlZCBvbiBmYWN0b3JzIEFnZSwgTGFuZ3VhZ2UsIG9yIERpcmVjdGlvbi4gVGhhdCdzIGdvb2QsIG1lYW5zIHRoZSB2aWRlb3Mgd2VyZSBlcXVhbGx5IGVuZ2FnaW5nIGZvciBhbGwgYmFiaWVzLCByaWdodD8gCgpgYGB7cn0KYmFiaWVzJGxhbmcgPC0gYXMuZmFjdG9yKGJhYmllcyRsYW5nKQpiYWJpZXNfb3ZlcmFsbF9sb29raW5nIDwtIGJhYmllcyAlPiUKICBncm91cF9ieShuYW1lLCBhZ2UsIGxhbmcsIGRpcmVjdGlvbiwgc3RvcnksIHJlcGV0aXRpb24pICU+JQogIHN1bW1hcmlzZShwZXJjZW50ID0gc3VtKHBlcmNlbnQpKSAjIGdldHMgdG90YWwgbG9va2luZyBwZXJjZW50IGZvciBlYWNoIHRyaWFsIGZvciBlYWNoIGJhYnkKCiMgVGFibGUgb2YgbWVhbnMKYmFiaWVzX292ZXJhbGxfbG9va2luZyAlPiUgCiAgZ3JvdXBfYnkobmFtZSwgbGFuZywgZGlyZWN0aW9uKSAlPiUKICBzdW1tYXJpc2UocGVyY2VudCA9IG1lYW4ocGVyY2VudCkpICU+JSAjIGdldCBhdmVyYWdlIGxvb2tpbmcgcGVyY2VudCBmb3IgZWFjaCBiYWJ5CiAgZ3JvdXBfYnkobGFuZywgZGlyZWN0aW9uKSAlPiUKICBzdW1tYXJpc2UobWVhbl9wZXJjZW50ID0gbWVhbihwZXJjZW50KSwKICAgICAgICAgICAgY291bnQgPSBuKCksCiAgICAgICAgICAgIHNkID0gc2QocGVyY2VudCksCiAgICAgICAgICAgIHNlID0gc2Qvc3FydChjb3VudCkpICU+JQogIHNlbGVjdCgtc2QpICU+JQogIHByaW50KCkKCmdncGxvdChiYWJpZXNfb3ZlcmFsbF9sb29raW5nLCBhZXMoeCA9IGFnZSwgeSA9IHBlcmNlbnQsIGNvbG9yID0gZGlyZWN0aW9uLCBmaWxsID0gZGlyZWN0aW9uKSkgKyAKICBnZW9tX2ppdHRlcihhbHBoYSA9IDAuNSkgKwogIGZhY2V0X2dyaWQoLiB+IGxhbmcpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFKSArCiAgZ2d0aXRsZSgiVmlkZW8gQXR0ZW50aW9uIikgKwogIHhsYWIoImFnZSAobW9udGhzKSIpICsKICB5bGFiKCJwZXJjZW50IGxvb2tpbmciKSArIAogIHRoZW1lX2J3KCkgKyAKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLDEpLCBsYWJlbHMgPSBwZXJjZW50KSAKCgojIFBsb3QKIyBiYWJpZXNfb3ZlcmFsbF9sb29raW5nICU+JSAKIyAgIGdyb3VwX2J5KGxhbmcsIGRpcmVjdGlvbiwgbmFtZSkgJT4lCiMgICBzdW1tYXJpc2UocGVyY2VudCA9IG1lYW4ocGVyY2VudCkpICU+JSAjIGdldHMgYXZlcmFnZSBsb29raW5nIHBlcmNlbnQgZm9yIGVhY2ggYmFieQojICAgZ3JvdXBfYnkobGFuZywgZGlyZWN0aW9uKSAlPiUKIyAgIHN1bW1hcmlzZShtZWFuX3BlcmNlbnQgPSBtZWFuKHBlcmNlbnQpLCAjIGdldHMgZ3JvdXAgYXZlcmFnZXMKIyAgICAgICAgICAgICBjb3VudCA9IG4oKSwKIyAgICAgICAgICAgICBzZCA9IHNkKHBlcmNlbnQpLAojICAgICAgICAgICAgIHNlID0gc2Qvc3FydChjb3VudCkpICU+JSAKIyAgIGdncGxvdChhZXMoeCA9IGxhbmcsIHkgPSBtZWFuX3BlcmNlbnQsIGZpbGwgPSBkaXJlY3Rpb24pKSArIAojICAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiKSArIAojICAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IG1lYW5fcGVyY2VudCAtIHNlLCB5bWF4ID0gbWVhbl9wZXJjZW50ICsgc2UpLCAKIyAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOSksIHdpZHRoID0gMC4yNSkgKyAKIyAgIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsMSksIGxhYmVscyA9IHBlcmNlbnQpICsKIyAgIHRoZW1lX21pbmltYWwoKSArIAojICAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpKSArCiMgIyAgZmFjZXRfd3JhcCgibGFuZyIpICsKIyAgIGdndGl0bGUoIlZpZGVvIEF0dGVudGlvbiIpICsKIyAgIHhsYWIoIiIpICsKIyAgIHlsYWIoInBlcmNlbnQgbG9va2luZyIpCgojIGJhYmllc19vdmVyYWxsX2xvb2tpbmcgJT4lCiMgICBnZ3Bsb3QoYWVzKHggPSBsYW5nLCB5ID0gcGVyY2VudCwgZmlsbCA9IGRpcmVjdGlvbikpICsKIyAgIGZhY2V0X3dyYXAoImFnZWdyb3VwIikgKyAKIyAgIGdlb21fdmlvbGluKCkKYGBgCgpBIGxpbmVhciBtb2RlbCBzaG93cyB0aGVyZSB3ZXJlIG5vIHNpZ25pZmljYW50IGVmZmVjdHMgb2YgYW55IGZhY3RvcnMuIFdlIGNhbiBjb25jbHVkZSB0aGVyZSB3YXMgbm8gZWZmZWN0IG9uIGhvdyAqbXVjaCogdGhlIGJhYmllcyBsb29rZWQgYXQgdGhlIHN0aW11bGkuICAKCmBgYHtyfQpnbG9iYWxfbG0gPC0gbG1lcihwZXJjZW50IH4gYWdlICsgbGFuZyAqIGRpcmVjdGlvbiArIChkaXJlY3Rpb258bmFtZSkgKyAoZGlyZWN0aW9ufHN0b3J5KSwgZGF0YSA9IGJhYmllc19vdmVyYWxsX2xvb2tpbmcpCnN1bW1hcnkoZ2xvYmFsX2xtKSAKI2dnY29lZihnbG9iYWxfbG0pCmBgYAoKIyBBT0kgTG9va2luZwpOb3cgd2UnbGwgcmUtY2FsY3VsYXRlIHRoZSBwZXJjZW50YWdlcyBzbyB0aGUgZGVub21pbmF0b3IgaXMgYmFzZWQgb24gdG90YWwgbG9va2luZyB0aW1lLiBBbGwgQU9JcyBzaG91bGQgc3VtIHVwIHRvIDEwMCUgZm9yIGVhY2ggdHJpYWwgYW5kIGVhY2ggYmFieS4gTmV4dCBsZXQncyBtYWtlIGEgYm94cGxvdCBvZiBhbGwgQU9Jcy4gCgpgYGB7cn0KI1JlY2FsY3VsYXRlIHBlcmNlbnQKYmFiaWVzIDwtIGJhYmllcyAlPiUKICBzZWxlY3QoLXBlcmNlbnQpICU+JQogIGdyb3VwX2J5KG5hbWUsIGxhbmcsIGFnZWdyb3VwLCBhZ2UsIGRpcmVjdGlvbiwgc3RvcnksIG1hcmssIHRyaWFsLCByZXBldGl0aW9uLCBnZW5kZXIpICU+JQogIG11dGF0ZSh0b3RhbHNlYyA9IHN1bShzZWNzKSkgJT4lCiAgZ3JvdXBfYnkobmFtZSwgbGFuZywgYWdlZ3JvdXAsIGFnZSwgZGlyZWN0aW9uLCBzdG9yeSwgbWFyaywgdHJpYWwsIHJlcGV0aXRpb24sIGdlbmRlciwgYW9pKSAlPiUKICBtdXRhdGUocGVyY2VudCA9IHNlY3MvdG90YWxzZWMpCgojIEJveHBsb3QKYmFiaWVzICU+JQogIGdncGxvdChhZXMoeCA9IGFvaSwgeSA9IHBlcmNlbnQsIGZpbGwgPSBkaXJlY3Rpb24pKSArIAogIGdlb21fYm94cGxvdCgpICsKICBnZ3RpdGxlKCJBT0kgQXR0ZW50aW9uIikgKwogIHRoZW1lX2J3KCkgKyAKICB4bGFiKCIiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUsIGhqdXN0ID0gMSksCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudCwgbGltaXRzID0gYygwLDEpKQpgYGAKSXQgYXBwZWFycyB0d28gaW1wb3J0YW50IEFPSXMgYXJlIE1pZENoZXN0VG9wIGFuZCBNaWRGYWNlQm90dG9tLiBMZXQncyBsb29rIGFnYWluIG9ubHkgYXQgbWlkbGluZSBBT0lzOgoKYGBge3J9Cm1pZGxpbmUgPSBjKCJCZWxseSIsIkJlbG93Q2hlc3QiLCJNaWRDaGVzdEJvdHRvbSIsIk1pZENoZXN0Q2VudGVyIiwiTWlkQ2hlc3RUb3AiLAogICAgICAgICAgICAiTWlkRmFjZUJvdHRvbSIsIk1pZEZhY2VDZW50ZXIiLCJNaWRGYWNlVG9wIikKYmFiaWVzICU+JQogIGZpbHRlcihhb2kgJWluJSBtaWRsaW5lKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBhb2ksIHkgPSBwZXJjZW50LCBmaWxsID0gZGlyZWN0aW9uKSkgKyAKICBnZW9tX2JveHBsb3QoKSArCiAgZ2d0aXRsZSgiTWlkbGluZSBBT0kgQXR0ZW50aW9uIikgKwogIHRoZW1lX2J3KCkgKyAKICB4bGFiKCIiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUsIGhqdXN0ID0gMSksCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudCwgbGltaXRzID0gYygwLDEpKQpgYGAKCkknbSBnb2luZyB0byBydW4gbGluZWFyIG1vZGVscyB3aXRoIG9ubHkgTWlkQ2hlc3RUb3Agb3IgTWlkRmFjZUJvdHRvbSwgYW5kIHNlZSB3aGF0IGhhcHBlbnMuIE5vIGFnZSBpbnRlcmFjdGlvbnMuCgoqKk1pZENoZXN0VG9wOioqCgoqIFNpZ25pZmljYW50IGVmZmVjdCBvZiBhZ2UgKHAgPSAwLjAwNCkgLSBvbGRlciBiYWJpZXMgbG9vayBhdCBNaWRDaGVzdFRvcCBBT0kgbW9yZS4KKiBTaWduaWZpY2FudCBlZmZlY3Qgb2YgbGFuZ3VhZ2UgKHAgPSAwLjAwNikgLSBOU0UgYmFiaWVzIGxvb2sgKzE0LjYlIG1vcmUgdGhhbiBTRSBiYWJpZXMuIAoqIFNpZ25pZmljYW50IGVmZmVjdCBvZiBkaXJlY3Rpb24gKHAgPSAwLjA0NikgLSBCYWJpZXMgbG9vayBhYm91dCA0LjUlIGxlc3MgZm9yIHJldmVyc2VkCiogTm8gbGFuZ3VhZ2UgWCBkaXJlY3Rpb24gaW50ZXJhY3Rpb24uIAoKKipNaWRGYWNlQm90dG9tOioqIAoKKiBObyBlZmZlY3Qgb2YgYWdlCiogU2lnbmlmaWNhbnQgZWZmZWN0IG9mIGxhbmd1YWdlIChwID0gMC4wMDQpIC0gU0UgYmFiaWVzIGxvb2sgKzIxJSBtb3JlIHRoYW4gTlNFIGJhYmllcy4KKiBNYXJnaW5hbCBlZmZlY3Qgb2YgbGFuZ3VhZ2UgKHAgPSAwLjA3MykgLSBCYWJpZXMgbG9vayBhYm91dCAyJSBtb3JlIGZvciByZXZlcnNlZC4gCiogTm8gbGFuZ3VhZ2UgWCBkaXJlY3Rpb24gaW50ZXJhY3Rpb24uCgpgYGB7cn0KYmFiaWVzICU+JQogIGZpbHRlcihhb2kgJWluJSBjKCJNaWRGYWNlQm90dG9tIiwiTWlkQ2hlc3RUb3AiKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gYWdlLCB5ID0gcGVyY2VudCwgY29sb3IgPSBkaXJlY3Rpb24sIGZpbGwgPSBkaXJlY3Rpb24pKSArIAogIGdlb21faml0dGVyKGFscGhhID0gMC41KSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLDEpLCBsYWJlbHMgPSBwZXJjZW50KSArCiAgdGhlbWVfYncoKSArIAojICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCkpICsKICBmYWNldF9ncmlkKGFvaSB+IGxhbmcpICsKICBnZ3RpdGxlKCJBT0kgQXR0ZW50aW9uIikgKwogIHhsYWIoIiIpICsKICB5bGFiKCJwZXJjZW50IGxvb2tpbmciKQoKbWlkY2hlc3R0b3BfbG0gPC0gbG1lcihwZXJjZW50IH4gYWdlICsgbGFuZyAqIGRpcmVjdGlvbiArICgxfG5hbWUpICsgKDF8c3RvcnkpLCBkYXRhID0gZmlsdGVyKGJhYmllcywgYW9pID09ICJNaWRDaGVzdFRvcCIpKQpzdW1tYXJ5KG1pZGNoZXN0dG9wX2xtKQojZ2djb2VmKG1pZGNoZXN0dG9wX2xtKQoKbWlkZmFjZWJvdHRvbV9sbSA8LSBsbWVyKHBlcmNlbnQgfiBhZ2UgKyBsYW5nICogZGlyZWN0aW9uICsgKDF8bmFtZSkgKyAoMXxzdG9yeSksIGRhdGEgPSBmaWx0ZXIoYmFiaWVzLCBhb2kgPT0gIk1pZEZhY2VCb3R0b20iKSkKc3VtbWFyeShtaWRmYWNlYm90dG9tX2xtKQojZ2djb2VmKG1pZGZhY2Vib3R0b21fbG0pCgojIEJhciBjaGFydAojIGJhYmllcyAlPiUKIyAgIGZpbHRlcihhb2kgJWluJSBjKCJNaWRGYWNlQm90dG9tIiwiTWlkQ2hlc3RUb3AiKSkgJT4lCiMgICBncm91cF9ieShhZ2Vncm91cCwgbGFuZywgZGlyZWN0aW9uLCBuYW1lLCBhb2kpICU+JQojICAgc3VtbWFyaXNlKHBlcmNlbnQgPSBtZWFuKHBlcmNlbnQpKSAlPiUgIyBnZXRzIGF2ZXJhZ2UgbG9va2luZyBwZXJjZW50IGZvciBlYWNoIGJhYnkKIyAgIGdyb3VwX2J5KGFnZWdyb3VwLCBsYW5nLCBkaXJlY3Rpb24sIGFvaSkgJT4lCiMgICBzdW1tYXJpc2UobWVhbl9wZXJjZW50ID0gbWVhbihwZXJjZW50KSwgIyBnZXRzIGdyb3VwIGF2ZXJhZ2VzCiMgICAgICAgICAgICAgY291bnQgPSBuKCksCiMgICAgICAgICAgICAgc2QgPSBzZChwZXJjZW50KSwKIyAgICAgICAgICAgICBzZSA9IHNkL3NxcnQoY291bnQpKSAlPiUgCiMgICBnZ3Bsb3QoYWVzKHggPSBsYW5nLCB5ID0gbWVhbl9wZXJjZW50LCBmaWxsID0gZGlyZWN0aW9uKSkgKyAKIyAgIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIikgKyAKIyAgIGdlb21fZXJyb3JiYXIoYWVzKHltaW4gPSBtZWFuX3BlcmNlbnQgLSBzZSwgeW1heCA9IG1lYW5fcGVyY2VudCArIHNlKSwgCiMgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjkpLCB3aWR0aCA9IDAuMjUpICsgCiMgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLDEpLCBsYWJlbHMgPSBwZXJjZW50KSArCiMgICB0aGVtZV9taW5pbWFsKCkgKyAKIyAgIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfYmxhbmsoKSkgKwojICAgZmFjZXRfZ3JpZChhb2kgfiBhZ2Vncm91cCkgKwojICAgZ2d0aXRsZSgiVmlkZW8gQXR0ZW50aW9uIikgKwojICAgeGxhYigiIikgKwojICAgeWxhYigicGVyY2VudCBsb29raW5nIikKYGBgCgoKIyBGYWNlLUNoZXN0IFJhdGlvCk5leHQsIHdlJ2xsIGRlZmluZSBhIEZhY2UtQ2hlc3QgUmF0aW8gKEZDUikgc3VjaCB0aGF0OgoKMS4gTWlkRmFjZUNlbnRlciwgTWlkRmFjZUJvdHRvbSA9IEZhY2UKMS4gTWlkQ2hlc3RUb3AsIE1pZENoZXN0Q2VudGVyLCBNaWRDaGVzdEJvdHRvbSwgQmVsb3dDaGVzdCA9IENoZXN0CjEuIEZDUiA9IGZhY2UgLSBjaGVzdCAvIGZhY2UgKyBjaGVzdAoKV2UgZGlkIG5vdCBpbmNsdWRlIEJlbGx5IG9yIE1pZEZhY2VUb3AgYmVjYXVzZSBvZiB2ZXJ5IGxvdyBsb29raW5nIHJhdGVzIGFjY29yZGluZyB0byB0aGUgYm94cGxvdHMgYWJvdmUuCgpgYGB7cn0KYmFiaWVzX2ZjciA8LSBiYWJpZXMgJT4lCiAgc3ByZWFkKGFvaSxwZXJjZW50KSAlPiUKICBncm91cF9ieShuYW1lLCBhZ2UsIGFnZWdyb3VwLCBsYW5nLCBnZW5kZXIsIGRpcmVjdGlvbiwgc3RvcnksIHJlcGV0aXRpb24pICU+JQogIHN1bW1hcmlzZShmYWNlID0gc3VtKE1pZEZhY2VDZW50ZXIsIE1pZEZhY2VCb3R0b20sIG5hLnJtID0gVFJVRSksCiAgICAgICAgIGNoZXN0ID0gc3VtKE1pZENoZXN0VG9wLCBNaWRDaGVzdENlbnRlciwgTWlkQ2hlc3RCb3R0b20sIEJlbG93Q2hlc3QsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIGZjciA9IChmYWNlIC0gY2hlc3QpIC8gKGZhY2UgKyBjaGVzdCkpCgojIFRhYmxlIG9mIG1lYW5zCmJhYmllc19mY3IgJT4lIAogIGdyb3VwX2J5KGxhbmcsIGRpcmVjdGlvbiwgbmFtZSkgJT4lCiAgc3VtbWFyaXNlKGZjciA9IG1lYW4oZmNyKSkgJT4lICMgZ2V0cyBhdmVyYWdlIGxvb2tpbmcgcGVyY2VudCBmb3IgZWFjaCBiYWJ5CiAgZ3JvdXBfYnkobGFuZywgZGlyZWN0aW9uKSAlPiUKICBzdW1tYXJpc2UobWVhbl9mY3IgPSBtZWFuKGZjciksICMgZ2V0cyBncm91cCBhdmVyYWdlcwogICAgICAgICAgICBjb3VudCA9IG4oKSwKICAgICAgICAgICAgc2QgPSBzZChmY3IpLAogICAgICAgICAgICBzZSA9IHNkL3NxcnQoY291bnQpKSAlPiUKICBzZWxlY3QoLXNkKSAlPiUKICBwcmludCgpCgojIFBsb3QKZ2dwbG90KGJhYmllc19mY3IsIGFlcyh4ID0gYWdlLCB5ID0gZmNyLCBjb2xvciA9IGRpcmVjdGlvbiwgZmlsbCA9IGRpcmVjdGlvbikpICsgCiAgZ2VvbV9qaXR0ZXIoYWxwaGEgPSAwLjUpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKC0xLDEpKSArCiAgdGhlbWVfYncoKSArIAogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIGZhY2V0X2dyaWQoLiB+IGxhbmcpICsKICBnZ3RpdGxlKCJGYWNlLUNoZXN0IFJhdGlvcyIpICsKICB4bGFiKCIiKSArCiAgeWxhYigiRkNSIikKCiMgQmFyIGNoYXJ0CiMgYmFiaWVzX2ZjciAlPiUgCiMgICBncm91cF9ieShhZ2Vncm91cCwgbGFuZywgZGlyZWN0aW9uLCBuYW1lKSAlPiUKIyAgIHN1bW1hcmlzZShmY3IgPSBtZWFuKGZjcikpICU+JSAjIGdldHMgYXZlcmFnZSBsb29raW5nIHBlcmNlbnQgZm9yIGVhY2ggYmFieQojICAgZ3JvdXBfYnkoYWdlZ3JvdXAsIGxhbmcsIGRpcmVjdGlvbikgJT4lCiMgICBzdW1tYXJpc2UobWVhbl9mY3IgPSBtZWFuKGZjciksICMgZ2V0cyBncm91cCBhdmVyYWdlcwojICAgICAgICAgICAgIGNvdW50ID0gbigpLAojICAgICAgICAgICAgIHNkID0gc2QoZmNyKSwKIyAgICAgICAgICAgICBzZSA9IHNkL3NxcnQoY291bnQpKSAlPiUgCiMgICBnZ3Bsb3QoYWVzKHggPSBsYW5nLCB5ID0gbWVhbl9mY3IsIGZpbGwgPSBkaXJlY3Rpb24pKSArIAojICAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiKSArIAojICAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IG1lYW5fZmNyIC0gc2UsIHltYXggPSBtZWFuX2ZjciArIHNlKSwgCiMgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjkpLCB3aWR0aCA9IDAuMjUpICsgCiMgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygtMSwxKSkgKwojICAgdGhlbWVfbWluaW1hbCgpICsgCiMgICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCkpICsKIyAgIGZhY2V0X3dyYXAoImFnZWdyb3VwIikgKwojICAgZ2d0aXRsZSgiRmFjZS1DaGVzdCBSYXRpb3MiKSArCiMgICB4bGFiKCIiKSArCiMgICB5bGFiKCJGQ1IiKQpgYGAKCldoYXQgd2lsbCBhIGxpbmVhciBtaXhlZCBtb2RlbCB0ZWxsIHVzPyAod2l0aCBubyBhZ2UgaW50ZXJhY3Rpb25zKQoKKiBObyBlZmZlY3Qgb2YgYWdlLiBJbnRlcmVzdGluZy4gTWF5YmUgYmVjYXVzZSB3ZSBkb24ndCBoYXZlIHRoYXQgbWFueSBiYWJpZXMuIAoqIFN0cm9uZyBlZmZlY3Qgb2YgbGFuZ3VhZ2U6IFNFIGJhYmllcyBoYXZlIG92ZXJhbGwgKzAuNTAgRkNSIHRoYW4gTlNFIGJhYmllcyAocCA9IDAuMDA4KTsgaW4gb3RoZXIgd29yZHMsIHRoZXkgYXJlIG1vcmUgYXR0cmFjdGVkIHRvIHRoZSBmYWNlLiAKKiBFZmZlY3Qgb2YgZGlyZWN0aW9uOiBSZXZlcnNhbCAqaW5jcmVhc2VzKiBGQ1IgYnkgKzAuMTIgYWNyb3NzIGFsbCBiYWJpZXMgKHAgPSAwLjAzMikuIEludGVyZXN0aW5nLgoqIFdlYWsgbGFuZ3VhZ2UgeCBkaXJlY3Rpb24gaW50ZXJhY3Rpb24uIEl0IHNlZW1zIE5TRSBiYWJpZXMgaGF2ZSBhIGJpZ2dlciByZXZlcnNhbCBlZmZlY3QgdGhhbiBTRSBiYWJpZXM/IFRyeWluZyB0byBqdWRnZSBmcm9tIHRoZSBoZWF0IG1hcHMuIChwID0gMC4wOTUpLiBCVXQgaXQncyBzbyB3ZWFrIHNvIHBvc3NpYmx5IG5vdCB3b3J0aCBtZW50aW9uaW5nLgoKCmBgYHtyfQpmY3JfbG0gPC0gbG1lcihmY3IgfiBhZ2UgKyBsYW5nICogZGlyZWN0aW9uICsgKDF8bmFtZSkgKyAoMXxzdG9yeSksIGRhdGEgPSBiYWJpZXNfZmNyKQpzdW1tYXJ5KGZjcl9sbSkKI2dnY29lZihmY3JfbG0pCmBgYAoKIyBIZWF0IE1hcHMKQW5kIG5vdyBoZWF0IG1hcHMhCgpgYGB7cn0KaGVhdG1hcF9iYWJpZXMgPC0gYmFiaWVzICU+JQogIGZpbHRlcihhb2kgJWluJSBtaWRsaW5lKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgZ3JvdXBfYnkobGFuZywgbmFtZSwgZGlyZWN0aW9uLCBhb2kpICU+JQogIHN1bW1hcmlzZShwZXJjZW50ID0gbWVhbihwZXJjZW50LCBuYS5ybT1UUlVFKSkgJT4lCiAgZ3JvdXBfYnkobGFuZywgZGlyZWN0aW9uLCBhb2kpICU+JQogIHN1bW1hcmlzZShwZXJjZW50ID0gbWVhbihwZXJjZW50LCBuYS5ybT1UUlVFKSkgJT4lCiAgdW5ncm91cCgpICU+JQogIG11dGF0ZShhb2kgPSBmYWN0b3IoYW9pLCBsZXZlbHMgPSBjKCJCZWxseSIsIkJlbG93Q2hlc3QiLCJNaWRDaGVzdEJvdHRvbSIsIk1pZENoZXN0Q2VudGVyIiwiTWlkQ2hlc3RUb3AiLAogICAgICAgICAgICAiTWlkRmFjZUJvdHRvbSIsIk1pZEZhY2VDZW50ZXIiLCJNaWRGYWNlVG9wIikpKQoKZ2dwbG90KGhlYXRtYXBfYmFiaWVzLCBhZXMoeCA9IGxhbmcsIHkgPSBhb2kpKSArCiAgZ2VvbV90aWxlKGFlcyhmaWxsPXBlcmNlbnQpLGNvbG9yPSJsaWdodGdyYXkiLG5hLnJtPVRSVUUpICsgCiMgIHNjYWxlX2ZpbGxfdmlyaWRpcyhvcHRpb24gPSAidmlyaWRpcyIsIGRpcmVjdGlvbj0tMSwgbGltaXRzID0gYygwLC43KSwgbGFiZWxzID0gcGVyY2VudCwgbmFtZSA9ICJsb29raW5nIHRpbWUiKSArCiAgICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICIjZmZmZmZmIiwgaGlnaCA9ICIjMDg1MTljIiwgc3BhY2UgPSAiTGFiIiwgbGltaXRzID0gYygwLC40NTEpLCBsYWJlbHMgPSBwZXJjZW50LCBuYW1lID0gImxvb2tpbmcgdGltZSIsIG5hLnZhbHVlID0gImdyZXk1MCIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExLCBjb2xvciA9ICJibGFjayIsIGZhY2UgPSAiaXRhbGljIiksIAogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gIndoaXRlIiwgZmlsbCA9ICJ3aGl0ZSIpLAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAid2hpdGUiKSkgKwogIGZhY2V0X2dyaWQoLiB+IGRpcmVjdGlvbikgKwogIHlsYWIoIiIpICsgeGxhYigiIikgKyBnZ3RpdGxlKCJFeWUgR2F6ZSBIZWF0IE1hcCwgYnkgRGlyZWN0aW9uIikgKyAKICBzY2FsZV95X2Rpc2NyZXRlKGV4cGFuZD1jKDAsMCkpICsKICBzY2FsZV94X2Rpc2NyZXRlKGV4cGFuZCA9IGMoMCwwKSkKCmdncGxvdChoZWF0bWFwX2JhYmllcywgYWVzKHggPSBkaXJlY3Rpb24sIHkgPSBhb2kpKSArCiAgZ2VvbV90aWxlKGFlcyhmaWxsPXBlcmNlbnQpLGNvbG9yPSJsaWdodGdyYXkiLG5hLnJtPVRSVUUpICsgCiMgIHNjYWxlX2ZpbGxfdmlyaWRpcyhvcHRpb24gPSAidmlyaWRpcyIsIGRpcmVjdGlvbj0tMSwgbGltaXRzID0gYygwLC43KSwgbGFiZWxzID0gcGVyY2VudCwgbmFtZSA9ICJsb29raW5nIHRpbWUiKSArCiAgICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICIjZmZmZmZmIiwgaGlnaCA9ICIjMDg1MTljIiwgc3BhY2UgPSAiTGFiIiwgbGltaXRzID0gYygwLC40NTEpLCBsYWJlbHMgPSBwZXJjZW50LCBuYW1lID0gImxvb2tpbmcgdGltZSIsIG5hLnZhbHVlID0gImdyZXk1MCIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExLCBjb2xvciA9ICJibGFjayIsIGZhY2UgPSAiaXRhbGljIiksIAogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gIndoaXRlIiwgZmlsbCA9ICJ3aGl0ZSIpLAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAid2hpdGUiKSkgKwogIGZhY2V0X2dyaWQoLiB+IGxhbmcpICsKICB5bGFiKCIiKSArIHhsYWIoIiIpICsgZ2d0aXRsZSgiRXllIEdhemUgSGVhdCBNYXAsIGJ5IExhbmd1YWdlIikgKyAKICBzY2FsZV95X2Rpc2NyZXRlKGV4cGFuZD1jKDAsMCkpICsKICBzY2FsZV94X2Rpc2NyZXRlKGV4cGFuZCA9IGMoMCwwKSkKYGBgCgojIERpZmZlcmVudCBXYXlzIHRvIFZpc3VhbGl6ZSBSZXZlcnNhbApJIHdhbnQgdG8gdHJ5IHRvIHZpc3VhbGl6ZSByZXZlcnNhbCBlZmZlY3RzIGEgZGlmZmVyZW50IHdheS4gTWF5YmUgdGhpcy4gCgpgYGB7cn0KIyBHZXQgcGFydGljaXBhbnQtbGV2ZWwgZGF0YQpiYWJpZXNfZmNyMiA8LSBiYWJpZXNfZmNyICU+JQogIGdyb3VwX2J5KG5hbWUsIGFnZSwgbGFuZywgZGlyZWN0aW9uKSAlPiUKICBzdW1tYXJpc2UoZmNyID0gbWVhbihmY3IpKQoKIyByZXZlcnNhbF9lZmZlY3RfbG0gPC0gbG1lcihmY3IgfiBhZ2UgKyBsYW5nICogZGlyZWN0aW9uICsgKDF8bmFtZSksIGRhdGEgPSBiYWJpZXNfZmNyMikKIyBzdW1tYXJ5KHJldmVyc2FsX2VmZmVjdF9sbSkKCmdncGxvdChiYWJpZXNfZmNyMiwgYWVzKHggPSBkaXJlY3Rpb24sIHkgPSBmY3IsIGNvbG9yID0gbGFuZywgZmlsbCA9IGxhbmcpKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX2xpbmUoYWVzKGdyb3VwID0gbmFtZSkpICsKICBmYWNldF9ncmlkKC4gfiBsYW5nKSArIAogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKC0xLDEpKSArCiAgdGhlbWVfYncoKQoKYGBgCgpPciBhIHJldmVyc2FsIGVmZmVjdCBjaGFydD8gT2theSwgc28gdGhpcyBjaGFydCB0ZWxscyB1cyBvdmVyYWxsIHRoZXJlIHJlYWxseSB3YXNuJ3QgbXVjaCBvZiBhIHJldmVyc2FsIGVmZmVjdCBmb3IgU0UgYmFiaWVzLCB0aGV5J3JlIGFsbCBob3ZlcmluZyBhcm91bmQgMC4gSW50ZXJlc3RpbmcuIFdoaWxlIHRoZXJlIHNlZW1zIHRvIGJlIGEgcmV2ZXJzYWwgZWZmZWN0IGZvciBOU0UgYmFiaWVzIHdoZXJlIHRoZXkgbG9vayBhdCB0aGUgZmFjZSBtb3JlIGR1cmluZyByZXZlcnNlZCBzdG9yaWVzISAKCmBgYHtyfQojIEdldCBwYXJ0aWNpcGFudC1sZXZlbCBkYXRhCmJhYmllc19mY3IzIDwtIGJhYmllc19mY3IyICU+JQogIHNwcmVhZChkaXJlY3Rpb24sIGZjcikgJT4lCiAgZ3JvdXBfYnkobmFtZSwgYWdlLCBsYW5nKSAlPiUKICBzdW1tYXJpc2UoZGlmZiA9IGZvcndhcmQgLSByZXZlcnNlZCkKCmdncGxvdChiYWJpZXNfZmNyMywgYWVzKHggPSBhZ2UsIHkgPSBkaWZmLCBjb2xvciA9IGxhbmcpKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoLTEsMSkpICsKICB0aGVtZV9idygpICsKICBnZ3RpdGxlKCJSZXZlcnNhbCBFZmZlY3QiKSArCiAgeWxhYigiRm9yd2FyZCBGQ1IgLSBSZXZlcnNlZCBGQ1IiKQpgYGAKClRoaXMgYW5hbHlzaXMgb2Ygd2l0aGluLXN1YmplY3QgdmFyaWF0aW9uIGhlcmU6IAoKYGBge3J9CiMgRmlyc3QgZ2V0IHRoZSBtZWFuIG9mIGVhY2ggdHJpYWwsIFRIRU4gdGhlIHBhcnRpY2lwYW50LWxldmVsIG1lYW5zCndpdGhpbl9zdWJqZWN0cyA8LSBiYWJpZXNfZmNyICU+JQogIGdyb3VwX2J5KG5hbWUsIGxhbmcsIGRpcmVjdGlvbiwgc3RvcnksIHJlcGV0aXRpb24pICU+JQogIHN1bW1hcmlzZShmY3IgPSBtZWFuKGZjciwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgY291bnQgPSBuKCkpICU+JQogIGdyb3VwX2J5KG5hbWUsIGxhbmcsIGRpcmVjdGlvbikgJT4lCiAgc3VtbWFyaXNlKG1lYW4gPSBtZWFuKGZjciwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgc2UgPSBzZChmY3IsIG5hLnJtID0gVFJVRSkvc3FydChuKCkpLAogICAgICAgICAgICBjb3VudCA9IG4oKSkKIyBUaGVuIHNwcmVhZCBvdXQgbWVhbiBhbmQgU0UgY29sdW1ucyBieSBkaXJlY3Rpb24Kd2l0aGluX3N1YmplY3RzX21lYW5zIDwtIHdpdGhpbl9zdWJqZWN0cyAlPiUKICBzZWxlY3QoLXNlLCAtY291bnQpICU+JQogIHNwcmVhZChkaXJlY3Rpb24sIG1lYW4sIHNlcCA9ICJfIikKd2l0aGluX3N1YmplY3RzX3NlIDwtIHdpdGhpbl9zdWJqZWN0cyAlPiUKICBzZWxlY3QoLW1lYW4sIC1jb3VudCkgJT4lCiAgc3ByZWFkKGRpcmVjdGlvbiwgc2UsIHNlcCA9ICJTRSIpCndpdGhpbl9zdWJqZWN0cyA8LSBsZWZ0X2pvaW4od2l0aGluX3N1YmplY3RzX21lYW5zLCB3aXRoaW5fc3ViamVjdHNfc2UsIGJ5ID0gYygibmFtZSIsImxhbmciKSkKCiMgTm93IGxldCdzIHBsb3QKbGltcyA8LSBjKC0xLDEpCndpdGhpbl9zdWJqZWN0cyAlPiUKICBnZ3Bsb3QoYWVzKHggPSBkaXJlY3Rpb25fZm9yd2FyZCwgeSA9IGRpcmVjdGlvbl9yZXZlcnNlZCwgY29sb3IgPSBsYW5nKSkgKwogIGdlb21fYWJsaW5lKCkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDIpICsgCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbj1kaXJlY3Rpb25fcmV2ZXJzZWQtZGlyZWN0aW9uU0VyZXZlcnNlZCwgeW1heD1kaXJlY3Rpb25fcmV2ZXJzZWQrZGlyZWN0aW9uU0VyZXZlcnNlZCkpICsKICBnZW9tX2Vycm9yYmFyaChhZXMoeG1pbj1kaXJlY3Rpb25fZm9yd2FyZC1kaXJlY3Rpb25TRWZvcndhcmQsIHhtYXg9ZGlyZWN0aW9uX2ZvcndhcmQrZGlyZWN0aW9uU0Vmb3J3YXJkKSkgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGFzcGVjdC5yYXRpbyA9IDEpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoImZvcndhcmQiLCBsaW1pdHMgPSBjKC0xLDEpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKCJyZXZlcnNlZCIsIGxpbWl0cyA9IGMoLTEsMSkpICsKICBnZ3RpdGxlKCJGQ1IgTWVhbnMiKSArCiAgZmFjZXRfd3JhcCgibGFuZyIpCmBgYAoKQW5kIGEgY2xhc3NpYyBib3gvZXJyb3IgcGxvdCB3aXRoIGFnZSBjb2xsYXBzZWQuIAoKYGBge3J9CmJhYmllc19mY3IyICU+JQogIGdyb3VwX2J5KGxhbmcsIGRpcmVjdGlvbikgJT4lCiAgc3VtbWFyaXNlKGZjcl9tZWFuID0gbWVhbihmY3IpLAogICAgICAgICAgICBzZCA9IHNkKGZjciksCiAgICAgICAgICAgIG4gPSBuKCksCiAgICAgICAgICAgIHNlID0gc2Qvc3FydChuKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gbGFuZywgeSA9IGZjcl9tZWFuLCBmaWxsID0gZGlyZWN0aW9uKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKCkpICsgCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IGZjcl9tZWFuLXNlLCB5bWF4ID0gZmNyX21lYW4rc2UpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuOSksIHdpZHRoID0gMC4yKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoLTAuNSwgMC41KSkgKwogIHRoZW1lX2xpbmVkcmF3KCkKCmBgYAoKIyBEaXNjdXNzaW9uIHJlIEFPSS9hbmF0b21pY2FsIGRhdGEKVGhlIGJpZ2dlc3QgY2hhbmdlIGlzIHdlIGxvc3QgdGhlIGludGVyYWN0aW9uIGJldHdlZW4gbGFuZ3VhZ2UgYW5kIGRpcmVjdGlvbi4gRm9yIHRoZSBJQ1NMQSBhYnN0cmFjdCB3ZSByZXBvcnRlZCBhIHN0cm9uZyBpbnRlcmFjdGlvbiAocCA9IDAuMDEpLCBidXQgbm93IGl0J3MgcCA9IDAuMTAuIFNob290LiAKClRoZSBpbnRlcnByZXRhdGlvbiBoZXJlIGlzIHRoYXQ6CgoqIEFsbCBiYWJpZXMgbG9va2VkIGVxdWFsbHkgYXQgYWxsIHZpZGVvcyByZWdhcmRsZXNzIG9mIGxhbmd1YWdlIG9yIGRpcmVjdGlvbi4gR29vZCEKKiBTRSBiYWJpZXMgYXJlIHN0cm9uZ2VyIGZhY2UtbG9va2VycyB0aGFuIE5TRSBiYWJpZXMuIChTYW1lIGFzIElDU0xBKQoqIFJldmVyc2FsIGFwcGVhcnMgdG8gYWZmZWN0IE5TRSBiYWJpZXMgbW9yZSB0aGFuIFNFIGJhYmllcz8gKE1hcmdpbmFsKS4gVGhpcyBpcyB1bmxpa2UgSUNTTEEuIAoKYGBge3IgZXZhbD1GQUxTRSwgZmlnLmhlaWdodD0xMiwgZmlnLndpZHRoPTEyLCBpbmNsdWRlPUZBTFNFfQojIENvcnJlbGF0aW9ucwoKIyBMZXQncyB0cnkgY29ycmVsYXRpb25zCmJhYmllc19uc2UgPC0gYmFiaWVzICU+JSAKICBmaWx0ZXIoYW9pICVpbiUgbWlkbGluZSkgJT4lCiAgZmlsdGVyKGxhbmcgPT0gIk5TRSIpICU+JQogIGdyb3VwX2J5KG5hbWUsIGRpcmVjdGlvbiwgYW9pKSAlPiUgCiAgc3VtbWFyaXNlKHBlcmNlbnQgPSBtZWFuKHBlcmNlbnQpKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgbXV0YXRlKGRpcmVjdGlvbiA9IGNhc2Vfd2hlbigKICAgIGRpcmVjdGlvbiA9PSAiZm9yd2FyZCIgfiAiZnciLAogICAgZGlyZWN0aW9uID09ICJyZXZlcnNlZCIgfiAicnYiCiAgKSkgJT4lIAogIHVuaXRlKGFvaTIsIGRpcmVjdGlvbiwgYW9pLCBzZXAgPSAiXyIpICU+JQogIHNwcmVhZChhb2kyLCBwZXJjZW50KSAlPiUKICBzZWxlY3QoLW5hbWUpCgpiYWJpZXNfc2UgPC0gYmFiaWVzICU+JSAKICBmaWx0ZXIoYW9pICVpbiUgbWlkbGluZSkgJT4lCiAgZmlsdGVyKGxhbmcgPT0gIlNFIikgJT4lCiAgZ3JvdXBfYnkobmFtZSwgZGlyZWN0aW9uLCBhb2kpICU+JSAKICBzdW1tYXJpc2UocGVyY2VudCA9IG1lYW4ocGVyY2VudCkpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBtdXRhdGUoZGlyZWN0aW9uID0gY2FzZV93aGVuKAogICAgZGlyZWN0aW9uID09ICJmb3J3YXJkIiB+ICJmdyIsCiAgICBkaXJlY3Rpb24gPT0gInJldmVyc2VkIiB+ICJydiIKICApKSAlPiUgCiAgdW5pdGUoYW9pMiwgZGlyZWN0aW9uLCBhb2ksIHNlcCA9ICJfIikgJT4lCiAgc3ByZWFkKGFvaTIsIHBlcmNlbnQpICU+JQogIHNlbGVjdCgtbmFtZSkKCmdnY29ycihiYWJpZXNfbnNlLCBsYWJlbCA9IFRSVUUsIGxhYmVsX3NpemUgPSA1LCBsYWJlbF9yb3VuZCA9IDIsIGxhYmVsX2FscGhhID0gVFJVRSwgaGp1c3QgPSAwLjksIHNpemUgPSA1LCBjb2xvciA9ICJncmV5NTAiLCBsYXlvdXQuZXhwID0gMSkgKyBnZ3RpdGxlKCJOU0UiKQoKZ2djb3JyKGJhYmllc19zZSwgbGFiZWwgPSBUUlVFLCBsYWJlbF9zaXplID0gNSwgbGFiZWxfcm91bmQgPSAyLCBsYWJlbF9hbHBoYSA9IFRSVUUsIGhqdXN0ID0gMC45LCBzaXplID0gNSwgY29sb3IgPSAiZ3JleTUwIiwgbGF5b3V0LmV4cCA9IDEpICsgZ2d0aXRsZSgiU0UiKQoKbGlicmFyeShjb3JycikKYmFiaWVzX25zZSAlPiUgY29ycmVsYXRlKCkgJT4lIG5ldHdvcmtfcGxvdChtaW5fY29yPTAuNikgKyBnZ3RpdGxlKCJOU0UgQmFiaWVzIikKYmFiaWVzX3NlICU+JSBjb3JyZWxhdGUoKSAlPiUgbmV0d29ya19wbG90KG1pbl9jb3I9MC42KSArIGdndGl0bGUoIlNFIEJhYmllcyIpCmBgYAoKIyBYWSBTcGFjZSBEYXRhCldlJ2xsIGxvYWQgdGhlIGRhdGEgZnJvbSB0aGUgYGNoaWxkeHlkYXRhLmZlYXRoZXJgIGZpbGUgbWFkZSBpbiAwNnJhd3h5ZGF0YS5SbWQuIFNvIGFueSBuZXcgYmFiaWVzLCBwbGVhc2UgcnVuIHRoZSBmaXJzdCBjb2RlIGJsb2NrIGluIDA2IHRvIGluY2x1ZGUgaXQuIFRoZW4gd2UnbGwga2VlcCBhbGwgdGhlIGJhYmllcyB3ZSBhbHNvIGhhdmUgaW4gdGhlIEFPSSBkYXRhIGdyb3VwLiAKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmluY2x1ZGVkIDwtIGJhYmllcyAlPiUKICB1bmdyb3VwKCkgJT4lCiAgc2VsZWN0KG5hbWUpICU+JSAKICBkaXN0aW5jdCgpICU+JQogIHVubGlzdCgpCgp4eWRhdGEgPC0gcmVhZF9mZWF0aGVyKCIuLi9DaGlsZCBEYXRhL2NoaWxkeHlkYXRhLmZlYXRoZXIiKSAlPiUKICByZW5hbWUobmFtZSA9IHBhcnRpY2lwYW50KSAlPiUKICBmaWx0ZXIobmFtZSAlaW4lIGluY2x1ZGVkKQoKIyBHZXQgYWdlcwphZ2VzIDwtIHJlYWRfY3N2KCJjaGlsZHJlbmFnZXMuY3N2IikgJT4lCiAgcmVuYW1lKG5hbWUgPSBwYXJ0aWNpcGFudCkKeHlkYXRhIDwtIHh5ZGF0YSAlPiUgbGVmdF9qb2luKGFnZXMsIGJ5ID0gIm5hbWUiKSAlPiUKICBtdXRhdGUoYWdlID0gYWdlKjEyKSAlPiUKICBtdXRhdGUoYWdlZ3JvdXAgPSBjYXNlX3doZW4oCiAgICBhZ2UgPD0gOC45OSB+ICJ5b3VuZ2VyIiwKICAgIGFnZSA+PSA5LjAgJiBhZ2UgPCAxNSB+ICJvbGRlciIKICApKSAlPiUKICBtdXRhdGUobGFuZ3VhZ2UgPSBjYXNlX3doZW4oCiAgICBsYW5ndWFnZSA9PSAiRW5nbGlzaEV4cG9zZWQiIH4gIk5TRSIsCiAgICBsYW5ndWFnZSA9PSAiU2lnbkxhbmd1YWdlRXhwb3NlZCIgfiAiU0UiCiAgKSkgJT4lCiAgcmVuYW1lKGxhbmcgPSBsYW5ndWFnZSkgJT4lCiAgc2VsZWN0KG5hbWUsIGdyb3VwLCBnZW5kZXIsIGxhbmcsIGNvbmRpdGlvbiwgbWFyaywgdHJpYWwsIHJlcGV0aXRpb24sIHgsIHksIGFnZSwgYWdlZ3JvdXApICU+JQogIHNlcGFyYXRlKGNvbmRpdGlvbiwgaW50byA9IGMoInN0b3J5IiwgImNsaXAiLCAiZGlyZWN0aW9uIikpICU+JQogIHVuaXRlKCJzdG9yeSIsIGMoInN0b3J5IiwgImNsaXAiKSkgJT4lCiAgbXV0YXRlKGRpcmVjdGlvbiA9IGNhc2Vfd2hlbigKICAgIGRpcmVjdGlvbiA9PSAiRVIiIH4gInJldmVyc2VkIiwKICAgIGRpcmVjdGlvbiA9PSAiRlciIH4gImZvcndhcmQiCiAgKSkgJT4lCiAgbXV0YXRlKG5hbWUgPSBmYWN0b3IobmFtZSksCiAgICAgICAgIGdyb3VwID0gZmFjdG9yKGdyb3VwKSwKICAgICAgICAgZ2VuZGVyID0gZmFjdG9yKGdlbmRlciksCiAgICAgICAgIGxhbmcgPSBmYWN0b3IobGFuZyksCiAgICAgICAgIHN0b3J5ID0gZmFjdG9yKHN0b3J5KSwKICAgICAgICAgZGlyZWN0aW9uID0gZmFjdG9yKGRpcmVjdGlvbiksCiAgICAgICAgIG1hcmsgPSBmYWN0b3IobWFyayksCiAgICAgICAgIHRyaWFsID0gZmFjdG9yKHRyaWFsKSwKICAgICAgICAgcmVwZXRpdGlvbiA9IGZhY3RvcihyZXBldGl0aW9uKSwKICAgICAgICAgYWdlZ3JvdXAgPSBmYWN0b3IoYWdlZ3JvdXApKQpgYGAKCiMjIE92ZXJhbGwgTG9va2luZwpMZXQncyBjaGVjayB0aGF0IHdlIGhhdmUgbm8gc2lnbmlmaWNhbnQgZ3JvdXAgb3IgY29uZGl0aW9uIGRpZmZlcmVuY2VzIGluIHRlcm1zIG9mIHZhbGlkIChub3QgZW1wdHkpIGRhdGEgcG9pbnRzIGNvbGxlY3RlZC4gVGhpcyBpcyBzYW1lIGFzICJHbG9iYWwgTG9va2luZyIgd2UgaGF2ZSBhYm92ZSwgcmVhbGx5LCBidXQgdyByYXcgeHkgZGF0YS4gCgpgYGB7cn0KeHlfb3ZlcmFsbCA8LSB4eWRhdGEgJT4lCiAgZmlsdGVyKCFpcy5uYSh4KSkgJT4lCiAgZ3JvdXBfYnkobmFtZSwgYWdlLCBsYW5nLCBkaXJlY3Rpb24sIHN0b3J5LCByZXBldGl0aW9uKSAlPiUKICBzdW1tYXJpc2UoZGF0YV9wb2ludHMgPSBuKCkpICMgZ2V0cyB0b3RhbCBsb29raW5nIHBlcmNlbnQgZm9yIGVhY2ggdHJpYWwgZm9yIGVhY2ggYmFieQoKIyBUYWJsZSBvZiBtZWFucwp4eV9vdmVyYWxsICU+JSAKICBncm91cF9ieShuYW1lLCBsYW5nLCBkaXJlY3Rpb24pICU+JQogIHN1bW1hcmlzZShkYXRhX3BvaW50cyA9IG1lYW4oZGF0YV9wb2ludHMpKSAlPiUgIyBnZXQgYXZlcmFnZSBsb29raW5nIHBlcmNlbnQgZm9yIGVhY2ggYmFieQogIGdyb3VwX2J5KGxhbmcsIGRpcmVjdGlvbikgJT4lCiAgc3VtbWFyaXNlKG1lYW5fZGF0YV9wb2ludHMgPSBtZWFuKGRhdGFfcG9pbnRzKSwKICAgICAgICAgICAgY291bnQgPSBuKCksCiAgICAgICAgICAgIHNkID0gc2QoZGF0YV9wb2ludHMpLAogICAgICAgICAgICBzZSA9IHNkL3NxcnQoY291bnQpKSAlPiUKICBzZWxlY3QoLXNkKSAlPiUKICBwcmludCgpCgpnZ3Bsb3QoeHlfb3ZlcmFsbCwgYWVzKHggPSBhZ2UsIHkgPSBkYXRhX3BvaW50cywgY29sb3IgPSBkaXJlY3Rpb24sIGZpbGwgPSBkaXJlY3Rpb24pKSArIAogIGdlb21faml0dGVyKGFscGhhID0gMC41KSArCiAgZmFjZXRfZ3JpZCguIH4gbGFuZykgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UpICsKICBnZ3RpdGxlKCJEYXRhIFBvaW50cyIpICsKICB4bGFiKCJhZ2UgKG1vbnRocykiKSArCiAgeWxhYigiZGF0YSBwb2ludHMgcmVjb3JkZWQiKSArIAogIHRoZW1lX2J3KCkgCmBgYAoKCkEgbGluZWFyIG1vZGVsIHNob3dzIHRoZXJlIHdlcmUgbm8gc2lnbmlmaWNhbnQgZWZmZWN0cyBvZiBhbnkgZmFjdG9ycy4gV2UgY2FuIGNvbmNsdWRlIHRoZXJlIHdhcyBubyBlZmZlY3Qgb24gaG93ICptdWNoKiBkYXRhIHdhcyBjb2xsZWN0ZWQgZnJvbSB0aGUgYmFiaWVzLiAgIAoKYGBge3J9Cm92ZXJhbGxfeHlfbG0gPC0gbG1lcihkYXRhX3BvaW50cyB+IGFnZSArIGxhbmcgKiBkaXJlY3Rpb24gKyAoZGlyZWN0aW9ufG5hbWUpICsgKGRpcmVjdGlvbnxzdG9yeSksIGRhdGEgPSB4eV9vdmVyYWxsKQpzdW1tYXJ5KG92ZXJhbGxfeHlfbG0pIAojZ2djb2VmKG92ZXJhbGxfeHlfbG0pCmBgYAoKIyMgWFkgRGF0YSBMTU1zCk5vdyB3ZSdyZSBnb2luZyB0byBydW4gTE1NcyBvbiBiYWJpZXMnIHJhdzogCgoqIGhvcml6b250YWwgc3ByZWFkIChtaWRkbGUgNTAlIG9mIHggZGF0YTsgeElRUikKKiB2ZXJ0aWNhbCBzcHJlYWQgKG1pZGRsZSA1MCUgb2YgeSBkYXRhOyB5SVFSKQoqIHZpZXdpbmcgYXJlYSAoQSA9IG1pZGRsZS14ICogbWlkZGxlLXk7IGFyZWEpCgpCdXQgdG8gZG8gdGhpcyB3ZSBmaXJzdCB0cmltIGVhY2ggYmFieSdzIGRhdGEsIGdldHRpbmcgcmlkIG9mIHRoZSBmaXJzdCA2MCBzYW1wbGVzICgwLjUgc2Vjcykgb2YgZWFjaCB0cmlhbC4gCgpgYGB7cn0KeHlkYXRhIDwtIHh5ZGF0YSAlPiUKICBncm91cF9ieShuYW1lLHRyaWFsKSAlPiUKICBzbGljZSg2MDpuKCkpCgppcXIgPC0geHlkYXRhICU+JQogIGdyb3VwX2J5KG5hbWUsIGFnZSwgbGFuZywgc3RvcnksIGRpcmVjdGlvbiwgdHJpYWwpICU+JQogIHN1bW1hcmlzZSh4SVFSID0gSVFSKHgsbmEucm09VFJVRSksCiAgICAgICAgICAgICAgICAgICB5SVFSID0gSVFSKHksbmEucm09VFJVRSksCiAgICAgICAgICAgICAgICAgICB4bWVkID0gbWVkaWFuKHgsIG5hLnJtPVRSVUUpLAogICAgICAgICAgICAgICAgICAgeW1lZCA9IG1lZGlhbih5LCBuYS5ybT1UUlVFKSwKICAgICAgICAgICAgICAgICAgIGFyZWEgPSB4SVFSKnlJUVIpCmhlYWQoaXFyLDIwKQoKYGBgCgoKIyMjIE1pZGRsZSBYCgpSZXN1bHRzIHRlbGwgdXMgdGhhdCB0aGVyZSBpcyBhIHNpZ25pZmljYW50IGVmZmVjdCBvZiBhZ2Ugd2hlcmUgaG9yaXpvbnRhbCBzcHJlYWQgZ3JldyBuYXJyb3dlciB3aXRoIG9sZGVyIGJhYmllcyAocCA9IDAuMDI0OyBzbG9wZSA9IC0yLjIgcHgvbW9udGgpLiBUaGVyZSB3YXMgYSBtYXJnaW5hbCBlZmZlY3Qgb2YgbGFuZ3VhZ2Ugd2hlcmUgU0UgYmFiaWVzIGhhdmUgc2xpZ2h0bHkgbmFycm93ZXIgaG9yaXpvbnRhbCBzcHJlYWQgKDExIHB4OyBwID0gMC4wODgpLiBObyBlZmZlY3RzIG9mIHJldmVyc2FsIG9yIGludGVyYWN0aW9ucy4KCmBgYHtyfQp4aXFyX21lYW4gPC0gaXFyICU+JSAKICBncm91cF9ieShsYW5nLCBkaXJlY3Rpb24sIG5hbWUpICU+JQogIHN1bW1hcmlzZSh4SVFSID0gbWVhbih4SVFSLCBuYS5ybSA9IFQpKSAlPiUgIyBnZXRzIGF2ZXJhZ2UgbG9va2luZyBwZXJjZW50IGZvciBlYWNoIGJhYnkKICBncm91cF9ieShsYW5nLCBkaXJlY3Rpb24pICU+JQogIHN1bW1hcmlzZShtZWFuX3hJUVIgPSBtZWFuKHhJUVIpLCAjIGdldHMgZ3JvdXAgYXZlcmFnZXMKICAgICAgICAgICAgY291bnQgPSBuKCksCiAgICAgICAgICAgIHNkID0gc2QoeElRUiksCiAgICAgICAgICAgIHNlID0gc2Qvc3FydChjb3VudCkpICU+JQogIHNlbGVjdCgtc2QpICU+JQogIHByaW50KCkKCiMgUGxvdApnZ3Bsb3QoaXFyLCBhZXMoeCA9IGFnZSwgeSA9IHhJUVIsIGNvbG9yID0gZGlyZWN0aW9uLCBmaWxsID0gZGlyZWN0aW9uKSkgKyAKICBnZW9tX2ppdHRlcihhbHBoYSA9IDAuNSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFKSArCiAgdGhlbWVfYncoKSArIAogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIGZhY2V0X2dyaWQoLiB+IGxhbmcpICsKICBnZ3RpdGxlKCJIb3Jpem9udGFsIFNwcmVhZCIpICsKICB4bGFiKCIiKSArCiAgeWxhYigieElRUiIpCgpnZ3Bsb3QoeGlxcl9tZWFuLCBhZXMoeCA9IGxhbmcsIHkgPSBtZWFuX3hJUVIsIGZpbGwgPSBkaXJlY3Rpb24pKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoKSkgKyAKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gbWVhbl94SVFSLXNlLCB5bWF4ID0gbWVhbl94SVFSK3NlKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjkpLCB3aWR0aCA9IDAuMikgKwogIHRoZW1lX2xpbmVkcmF3KCkKCnhpcXJfbG0gPC0gbG1lcih4SVFSIH4gYWdlICsgbGFuZyAqIGRpcmVjdGlvbiArICgxfG5hbWUpICsgKDF8c3RvcnkpLCBkYXRhID0gaXFyKQpzdW1tYXJ5KHhpcXJfbG0pCiNnZ2NvZWYoeGlxcl9sbSkKYGBgCgoKIyMjIE1pZGRsZSBZCgpXZSBoYWQgYSBzaWduaWZpY2FudCBlZmZlY3Qgb2YgYWdlIHdoZXJlIHZlcnRpY2FsIHNwcmVhZCBnb3QgbmFycm93ZXIgd2l0aCBvbGRlciBiYWJpZXMgKHAgPSAwLjAxOSwgc2xvcGUgPSAtNS41IHB4L21vbnRoKS4gVGhlcmUgd2VyZSBubyBlZmZlY3Qgb2YgbGFuZ3VhZ2UsIGRpcmVjdGlvbiwgb3IgaW50ZXJhY3Rpb25zLiAKCmBgYHtyfQp5aXFyX21lYW4gPC0gaXFyICU+JSAKICBncm91cF9ieShsYW5nLCBkaXJlY3Rpb24sIG5hbWUpICU+JQogIHN1bW1hcmlzZSh5SVFSID0gbWVhbih5SVFSLCBuYS5ybSA9IFQpKSAlPiUgIyBnZXRzIGF2ZXJhZ2UgbG9va2luZyBwZXJjZW50IGZvciBlYWNoIGJhYnkKICBncm91cF9ieShsYW5nLCBkaXJlY3Rpb24pICU+JQogIHN1bW1hcmlzZShtZWFuX3lJUVIgPSBtZWFuKHlJUVIpLCAjIGdldHMgZ3JvdXAgYXZlcmFnZXMKICAgICAgICAgICAgY291bnQgPSBuKCksCiAgICAgICAgICAgIHNkID0gc2QoeUlRUiksCiAgICAgICAgICAgIHNlID0gc2Qvc3FydChjb3VudCkpICU+JQogIHNlbGVjdCgtc2QpICU+JQogIHByaW50KCkKCiMgUGxvdApnZ3Bsb3QoaXFyLCBhZXMoeCA9IGFnZSwgeSA9IHlJUVIsIGNvbG9yID0gZGlyZWN0aW9uLCBmaWxsID0gZGlyZWN0aW9uKSkgKyAKICBnZW9tX2ppdHRlcihhbHBoYSA9IDAuNSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFKSArCiAgdGhlbWVfYncoKSArIAogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIGZhY2V0X2dyaWQoLiB+IGxhbmcpICsKICBnZ3RpdGxlKCJWZXJ0aWNhbCBTcHJlYWQiKSArCiAgeGxhYigiIikgKwogIHlsYWIoInlJUVIiKQoKZ2dwbG90KHlpcXJfbWVhbiwgYWVzKHggPSBsYW5nLCB5ID0gbWVhbl95SVFSLCBmaWxsID0gZGlyZWN0aW9uKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKCkpICsgCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IG1lYW5feUlRUi1zZSwgeW1heCA9IG1lYW5feUlRUitzZSksIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC45KSwgd2lkdGggPSAwLjIpICsKICB0aGVtZV9saW5lZHJhdygpCgp5aXFyX2xtIDwtIGxtZXIoeUlRUiB+IGFnZSArIGxhbmcgKiBkaXJlY3Rpb24gKyAoMXxuYW1lKSArICgxfHN0b3J5KSwgZGF0YSA9IGlxcikKc3VtbWFyeSh5aXFyX2xtKQojZ2djb2VmKHlpcXJfbG0pCmBgYAoKIyMjIFZpZXdpbmcgQXJlYQpBZ2FpbiwgYWdlIGlzIHNpZ25pZmljYW50IChwID0gMC4wMSkgc3VjaCB0aGF0IGFyZWEgZ2V0cyBzbWFsbGVyIHdpdGggYWdlIChhYm91dCA1MDAgc3EuIHB4LiBwZXIgbW9udGgpLiBObyBlZmZlY3Qgb2YgbGFuZ3VhZ2Ugb3IgZGlyZWN0aW9uIG9yIGludGVyYWN0aW9ucy4gCgpgYGB7cn0KYXJlYV9tZWFuIDwtIGlxciAlPiUgCiAgZ3JvdXBfYnkobGFuZywgZGlyZWN0aW9uLCBuYW1lKSAlPiUKICBzdW1tYXJpc2UoYXJlYSA9IG1lYW4oYXJlYSwgbmEucm0gPSBUKSkgJT4lICMgZ2V0cyBhdmVyYWdlIGxvb2tpbmcgcGVyY2VudCBmb3IgZWFjaCBiYWJ5CiAgZ3JvdXBfYnkobGFuZywgZGlyZWN0aW9uKSAlPiUKICBzdW1tYXJpc2UoYXJlYV9tZWFuID0gbWVhbihhcmVhKSwgIyBnZXRzIGdyb3VwIGF2ZXJhZ2VzCiAgICAgICAgICAgIGNvdW50ID0gbigpLAogICAgICAgICAgICBzZCA9IHNkKGFyZWEpLAogICAgICAgICAgICBzZSA9IHNkL3NxcnQoY291bnQpKSAlPiUKICBzZWxlY3QoLXNkKSAlPiUKICBwcmludCgpCgojIFBsb3QKZ2dwbG90KGlxciwgYWVzKHggPSBhZ2UsIHkgPSBhcmVhLCBjb2xvciA9IGRpcmVjdGlvbiwgZmlsbCA9IGRpcmVjdGlvbikpICsgCiAgZ2VvbV9qaXR0ZXIoYWxwaGEgPSAwLjUpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSkgKwogIHRoZW1lX2J3KCkgKyAKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCkpICsKICBmYWNldF9ncmlkKC4gfiBsYW5nKSArCiAgZ2d0aXRsZSgiVmlld2luZyBBcmVhIikgKwogIHhsYWIoIiIpICsKICB5bGFiKCJBcmVhIChweF4yKSIpCgpnZ3Bsb3QoYXJlYV9tZWFuLCBhZXMoeCA9IGxhbmcsIHkgPSBhcmVhX21lYW4sIGZpbGwgPSBkaXJlY3Rpb24pKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoKSkgKyAKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gYXJlYV9tZWFuLXNlLCB5bWF4ID0gYXJlYV9tZWFuK3NlKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjkpLCB3aWR0aCA9IDAuMikgKwogIHRoZW1lX2xpbmVkcmF3KCkKCmFyZWFfbG0gPC0gbG1lcihhcmVhIH4gYWdlICsgbGFuZyAqIGRpcmVjdGlvbiArICgxfG5hbWUpICsgKDF8c3RvcnkpLCBkYXRhID0gaXFyKQpzdW1tYXJ5KGFyZWFfbG0pCiNnZ2NvZWYoYXJlYV9sbSkKYGBgCgojIyBQbG90dGluZyBWaWV3aW5nIEFyZWEgCgpgYGB7cn0KbWVkaWFucyA8LSBpcXIgJT4lCiAgZ3JvdXBfYnkobmFtZSxsYW5nLGRpcmVjdGlvbikgJT4lCiAgc3VtbWFyaXNlKHhJUVIgPSBtZWRpYW4oeElRUixuYS5ybT1UUlVFKSwKICAgICAgICAgICAgICAgICAgIHlJUVIgPSBtZWRpYW4oeUlRUixuYS5ybT1UUlVFKSwKICAgICAgICAgICAgICAgICAgIHhtZWQgPSBtZWRpYW4oeG1lZCxuYS5ybT1UUlVFKSwKICAgICAgICAgICAgICAgICAgIHltZWQgPSBtZWRpYW4oeW1lZCxuYS5ybT1UUlVFKSkgJT4lCiAgZ3JvdXBfYnkobGFuZyxkaXJlY3Rpb24pICU+JSAKICBzdW1tYXJpc2UoeElRUiA9IG1lYW4oeElRUixuYS5ybT1UUlVFKSwKICAgICAgICAgICAgICAgICAgIHlJUVIgPSBtZWFuKHlJUVIsbmEucm09VFJVRSksCiAgICAgICAgICAgICAgICAgICB4ID0gbWVkaWFuKHhtZWQsbmEucm09VFJVRSksCiAgICAgICAgICAgICAgICAgICB5ID0gbWVkaWFuKHltZWQsbmEucm09VFJVRSkpICU+JQogIG11dGF0ZSh5ID0geSotMSwKICAgICAgICAgeG1pbiA9IHgtKHhJUVIvMiksCiAgICAgICAgIHhtYXggPSB4Kyh4SVFSLzIpLAogICAgICAgICB5bWluID0geS0oeUlRUi8yKSwKICAgICAgICAgeW1heCA9IHkrKHlJUVIvMikpCmltZyA8LSBwbmc6OnJlYWRQTkcoImNpbmR5LnBuZyIpCmcgPC0gZ3JpZDo6cmFzdGVyR3JvYihpbWcsIGludGVycG9sYXRlPVRSVUUsIHdpZHRoPXVuaXQoMSwibnBjIiksIGhlaWdodD11bml0KDEsIm5wYyIpKSAKZ2dwbG90KG1lZGlhbnMsIGFlcyhmaWxsPWRpcmVjdGlvbixjb2xvcj1kaXJlY3Rpb24pKSArCiAgYW5ub3RhdGlvbl9jdXN0b20oZywgeG1pbj0tSW5mLCB4bWF4PUluZiwgeW1pbj0tSW5mLCB5bWF4PUluZikgKwogIGdlb21fcmVjdChhZXMoeG1pbj14bWluLHltaW49eW1pbix4bWF4PXhtYXgseW1heD15bWF4KSxhbHBoYT0uMSkgKyAKICB0aGVtZV9saW5lZHJhdygpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLDEwODApLCBleHBhbmQgPSBjKDAsIDApKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoLTcyMCwwKSwgZXhwYW5kID0gYygwLCAwKSkgKwogIGZhY2V0X3dyYXAoImxhbmciKQpgYGAKCiMgUHVwcGllcwpHZXQgcHVwcHkgZGF0YSEKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMgcHVwcGllczEgPC0gcmVhZF90c3YoIi4uL0NoaWxkIERhdGEvX3B1cHBpZXMvYWxsIHB1cHBpZXMgZ3JvdXAgMSBzdW1zLnR4dCIsIG5hID0gIi0iKSAlPiUgCiMgICBjbGVhbl9uYW1lcygpICU+JQojICAgc2VsZWN0KC1jKGFnZSwgYW5hbHlzaXMsIGNoZWNrX2lmX3dhbnRfc2NhdHRlcnBsb3QsIGdlbmRlciwgbGFuZ3VhZ2UpKSAlPiUKIyAgIHJlbmFtZShuYW1lID0geDEpICU+JQojICAgbXV0YXRlKG1lYW4gPSByb3dNZWFucyguWzI6MTBdLCBuYS5ybSA9IFQpKSAlPiUKIyAgIHNlbGVjdChuYW1lLCBtZWFuKQojICAgCiMgcHVwcGllczIgPC0gcmVhZF90c3YoIi4uL0NoaWxkIERhdGEvX3B1cHBpZXMvYWxsIHB1cHBpZXMgZ3JvdXAgMiBzdW1zLnR4dCIsIG5hID0gIi0iKSAlPiUgCiMgICBjbGVhbl9uYW1lcygpICU+JQojICAgc2VsZWN0KC1jKGFnZSwgYW5hbHlzaXMsIGNoZWNrX2lmX3dhbnRfc2NhdHRlcnBsb3QsIGdlbmRlciwgbGFuZ3VhZ2UpKSAlPiUKIyAgIHJlbmFtZShuYW1lID0geDEpICU+JQojICAgbXV0YXRlKG1lYW4gPSByb3dNZWFucyguWzI6MTddLCBuYS5ybSA9IFQpKSAlPiUKIyAgIHNlbGVjdChuYW1lLCBtZWFuKQojIAojIHB1cHBpZXMgPC0gcmJpbmQocHVwcGllczEsIHB1cHBpZXMyKQojIAojIHBhcnRpY2lwYW50cyA8LSB4eWRhdGEgJT4lIAojICAgc2VsZWN0KG5hbWUsIGdyb3VwLCBnZW5kZXIsIGxhbmcpICU+JSAKIyAgIGRpc3RpbmN0KCkKIyAKIyBwdXBwaWVzIDwtIGxlZnRfam9pbihwYXJ0aWNpcGFudHMsIHB1cHBpZXMsIGJ5ID0gIm5hbWUiKQojIAojIHN1bW1hcnkobG0oZGF0YSA9IHB1cHBpZXMsIG1lYW4gfiBsYW5nKSkKIyAKIyBwdXBwaWVzX3NlIDwtIGZpbHRlcihwdXBwaWVzLCBsYW5nID09ICJOU0UiKQojIHB1cHBpZXNfbnNlIDwtIGZpbHRlcihwdXBwaWVzLCBsYW5nID09ICJTRSIpCiMgCiMgdC50ZXN0KHB1cHBpZXNfc2UkbWVhbiwgcHVwcGllc19uc2UkbWVhbikKCiMgTGV0J3MgZG8gdGhpcyBhZ2FpbiBidXQgcHJlc2VydmUgcHVwcHktbGV2ZWwgZGF0YQpwdXBwaWVzMSA8LSByZWFkX3RzdigiLi4vQ2hpbGQgRGF0YS9fcHVwcGllcy9hbGwgcHVwcGllcyBncm91cCAxIHN1bXMudHh0IiwgbmEgPSAiLSIpICU+JSAKICBjbGVhbl9uYW1lcygpICU+JQogIHNlbGVjdCgtYyhhZ2UsIGFuYWx5c2lzLCBjaGVja19pZl93YW50X3NjYXR0ZXJwbG90LCBnZW5kZXIsIGxhbmd1YWdlKSkgJT4lCiAgcmVuYW1lKG5hbWUgPSB4MSkgJT4lCiAgZ2F0aGVyKGtleSA9IHB1cHB5LCB2YWx1ZSA9IHNlYywgLW5hbWUpICU+JQogIG11dGF0ZShwdXBzID0gY2FzZV93aGVuKAogICAgc3RyX2RldGVjdChwdXBweSwgImh1c2tpZXMiKSB+ICJodXNraWVzIiwKICAgIHN0cl9kZXRlY3QocHVwcHksICJnb2xkZW4iKSB+ICJnb2xkZW4iLAogICAgc3RyX2RldGVjdChwdXBweSwgIndhd2EiKSB+ICJ3YXdhIiwKICAgIHN0cl9kZXRlY3QocHVwcHksICJmcmlzYnkiKSB+ICJmcmlzYnkiLAogICAgc3RyX2RldGVjdChwdXBweSwgImJ1bGxkb2ciKSB+ICJidWxsZG9nIiwKICAgIHN0cl9kZXRlY3QocHVwcHksICJwdXBweV9qcGciKSB+ICJwdXBweSIsCiAgICBUUlVFIH4gcHVwcHkKICApKQoKcHVwcGllczIgPC0gcmVhZF90c3YoIi4uL0NoaWxkIERhdGEvX3B1cHBpZXMvYWxsIHB1cHBpZXMgZ3JvdXAgMiBzdW1zLnR4dCIsIG5hID0gIi0iKSAlPiUgCiAgY2xlYW5fbmFtZXMoKSAlPiUKICBzZWxlY3QoLWMoYWdlLCBhbmFseXNpcywgY2hlY2tfaWZfd2FudF9zY2F0dGVycGxvdCwgZ2VuZGVyLCBsYW5ndWFnZSkpICU+JQogIHJlbmFtZShuYW1lID0geDEpICU+JQogIGdhdGhlcihrZXkgPSBwdXBweSwgdmFsdWUgPSBzZWMsIC1uYW1lKSAlPiUKICBtdXRhdGUocHVwcyA9IGNhc2Vfd2hlbigKICAgIHN0cl9kZXRlY3QocHVwcHksICJodXNraWVzIikgfiAiaHVza2llcyIsCiAgICBzdHJfZGV0ZWN0KHB1cHB5LCAiZ29sZGVuIikgfiAiZ29sZGVuIiwKICAgIHN0cl9kZXRlY3QocHVwcHksICJ3YXdhIikgfiAid2F3YSIsCiAgICBzdHJfZGV0ZWN0KHB1cHB5LCAiZnJpc2J5IikgfiAiZnJpc2J5IiwKICAgIHN0cl9kZXRlY3QocHVwcHksICJidWxsZG9nIikgfiAiYnVsbGRvZyIsCiAgICBzdHJfZGV0ZWN0KHB1cHB5LCAicHVwcGllcyIpIH4gInB1cHBpZXMiLAogICAgVFJVRSB+IHB1cHB5CiAgKSkKCnB1cHBpZXMgPC0gcmJpbmQocHVwcGllczEscHVwcGllczIpCgpwYXJ0aWNpcGFudHMgPC0geHlkYXRhICU+JQogIHNlbGVjdChuYW1lLCBncm91cCwgZ2VuZGVyLCBsYW5nKSAlPiUKICBkaXN0aW5jdCgpCgpwdXBwaWVzIDwtIGxlZnRfam9pbihwYXJ0aWNpcGFudHMsIHB1cHBpZXMsIGJ5ID0gIm5hbWUiKQoKc3VtbWFyeShsbWVyKGRhdGEgPSBwdXBwaWVzLCBzZWMgfiBsYW5nICsgKDF8bmFtZSkgKyAoMXxwdXBzKSkpCgpnZ3Bsb3QocHVwcGllcywgYWVzKHggPSBsYW5nLCB5ID0gc2VjLCBmaWxsID0gbGFuZykpICsgZ2VvbV9ib3hwbG90KCkKYGBgCgo=